You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@htrace.apache.org by cm...@apache.org on 2015/06/09 23:59:06 UTC
[01/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Repository: incubator-htrace
Updated Branches:
refs/heads/master 405105475 -> baaa3a528
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.min.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.min.js b/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.min.js
deleted file mode 100644
index 541911f..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// rome@v2.1.0, MIT licensed. https://github.com/bevacqua/rome
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.rome=t()}}(function(){return function t(e,n,r){function o(i,s){if(!n[i]){if(!e[i]){var u="function"==typeof require&&require;if(!s&&u)return u(i,!0);if(a)return a(i,!0);throw new Error("Cannot find module '"+i+"'")}var c=n[i]={exports:{}};e[i][0].call(c.exports,function(t){var n=e[i][1][t];return o(n?n:t)},c,c.exports,t,e,n,r)}return n[i].exports}for(var a="function"==typeof require&&require,i=0;i<r.length;i++)o(r[i]);return o}({1:[function(t,e){function n(){}var r=e.exports={};r.nextTick=function(){var t="undefined"!=typeof window&&window.setImmediate,e="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(t)return function(t){return window.setImmediate(t)};if(e){var n=[];return window.addEventListe
ner("message",function(t){var e=t.source;if((e===window||null===e)&&"process-tick"===t.data&&(t.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(t){n.push(t),window.postMessage("process-tick","*")}}return function(t){setTimeout(t,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.on=n,r.addListener=n,r.once=n,r.off=n,r.removeListener=n,r.removeAllListeners=n,r.emit=n,r.binding=function(){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(){throw new Error("process.chdir is not supported")}},{}],2:[function(t,e){e.exports=t("./src/contra.emitter.js")},{"./src/contra.emitter.js":3}],3:[function(t,e){(function(t){!function(n,r){"use strict";function o(t,e){return Array.prototype.slice.call(t,e)}function a(t,e,n){t&&s(function(){t.apply(n||null,e||[])})}function i(t,e){var n=e||{},i={};return t===r&&(t={}),t.on=function(e,n){return i[e]?i[e].push(n):i[e]=[n],t},t.once=function(e,n){return n._once=!0,t.on(e,n),t},t.o
ff=function(e,n){var r=arguments.length;if(1===r)delete i[e];else if(0===r)i={};else{var o=i[e];if(!o)return t;o.splice(o.indexOf(n),1)}return t},t.emit=function(){var e=o(arguments);return t.emitterSnapshot(e.shift()).apply(this,e)},t.emitterSnapshot=function(e){var r=(i[e]||[]).slice(0);return function(){var s=o(arguments),u=this||t;if("error"===e&&n.throws!==!1&&!r.length)throw 1===s.length?s[0]:s;return i[e]=r.filter(function(t){return n.async?a(t,s,u):t.apply(u,s),!t._once}),t}},t}var s,u=""+r,c="function"==typeof setImmediate;s=c?function(t){setImmediate(t)}:typeof t!==u&&t.nextTick?t.nextTick:function(t){setTimeout(t,0)},typeof e!==u&&e.exports?e.exports=i:(n.contra=n.contra||{},n.contra.emitter=i)}(this)}).call(this,t("FWaASH"))},{FWaASH:1}],4:[function(t,e){for(var n=t("performance-now"),r="undefined"==typeof window?{}:window,o=["moz","webkit"],a="AnimationFrame",i=r["request"+a],s=r["cancel"+a]||r["cancelRequest"+a],u=!0,c=0;c<o.length&&!i;c++)i=r[o[c]+"Request"+a],s=r[o[c
]+"Cancel"+a]||r[o[c]+"CancelRequest"+a];if(!i||!s){u=!1;var l=0,d=0,f=[],m=1e3/60;i=function(t){if(0===f.length){var e=n(),r=Math.max(0,m-(e-l));l=r+e,setTimeout(function(){var t=f.slice(0);f.length=0;for(var e=0;e<t.length;e++)if(!t[e].cancelled)try{t[e].callback(l)}catch(n){setTimeout(function(){throw n},0)}},Math.round(r))}return f.push({handle:++d,callback:t,cancelled:!1}),d},s=function(t){for(var e=0;e<f.length;e++)f[e].handle===t&&(f[e].cancelled=!0)}}e.exports=function(t){return u?i.call(r,function(){try{t.apply(this,arguments)}catch(e){setTimeout(function(){throw e},0)}}):i.call(r,t)},e.exports.cancel=function(){s.apply(r,arguments)}},{"performance-now":5}],5:[function(t,e){(function(t){(function(){var n,r,o;"undefined"!=typeof performance&&null!==performance&&performance.now?e.exports=function(){return performance.now()}:"undefined"!=typeof t&&null!==t&&t.hrtime?(e.exports=function(){return(n()-o)/1e6},r=t.hrtime,n=function(){var t;return t=r(),1e9*t[0]+t[1]},o=n()):Date.n
ow?(e.exports=function(){return Date.now()-o},o=Date.now()):(e.exports=function(){return(new Date).getTime()-o},o=(new Date).getTime())}).call(this)}).call(this,t("FWaASH"))},{FWaASH:1}],6:[function(t,e){"use strict";function n(t,e){var n=u[t.id];return n&&n[e.id]}function r(t,e){var n=u[t.id];n||(n=u[t.id]={});var r=a(e);n[e.id]=r,t.on("data",r),t.on("destroyed",o.bind(null,t,e))}function o(t,e){var n=u[t.id];if(n){var r=n[e.id];t.off("data",r),delete n[e.id]}}function a(t){return function(){t.refresh()}}function i(t,e){s(e.associated)||n(t,e)||r(t,e)}var s=t("./isInput"),u={};e.exports={add:i,remove:o}},{"./isInput":17}],7:[function(t,e){"use strict";function n(t){function e(){return Te}function n(n){return de=l(n||t,Te),ye||(ye=i({className:de.styles.container})),pe=de.weekdayFormat,he=pe.length,we=r,ve=r,be=r,ge=r,de.appendTo.appendChild(ye),J(ye),De=!1,fe=de.initialValue?de.initialValue:d.moment(),me=fe.clone(),Te.container=ye,Te.destroyed=!1,Te.destroy=h.bind(Te,!1),Te.emitVal
ues=z,Te.getDate=ue,Te.getDateString=ce,Te.getMoment=le,Te.hide=O,Te.options=w,Te.options.reset=b,Te.refresh=$,Te.restore=e,Te.setValue=G,Te.show=N,N(),v(),p(),Te}function p(){Te.emit("ready",c(de))}function h(t){ye&&ye.parentNode.removeChild(ye),de&&v(!0);var r=Te.emitterSnapshot("destroyed");return Te.destroyed=!0,Te.destroy=e,Te.emitValues=e,Te.getDate=y,Te.getDateString=y,Te.getMoment=y,Te.hide=e,Te.options=e,Te.options.reset=e,Te.refresh=e,Te.restore=n,Te.setValue=e,Te.show=e,Te.off(),t!==!0&&r(),Te}function v(t){var e=t?"remove":"add";de.autoHideOnBlur&&m[e](document.documentElement,"focus",H,!0),de.autoHideOnClick&&m[e](document,"click",S)}function w(t){return 0===arguments.length?c(de):(h(),n(t),Te)}function b(){return w({appendTo:de.appendTo})}function g(){De||(De=!0,x(),k(),Te.emit("render"))}function x(){function t(t){var e=i({className:de.styles.month,parent:xe});0===t&&(ke=i({type:"button",className:de.styles.back,attributes:{type:"button"},parent:e})),t===de.monthsInCa
lendar-1&&(Ee=i({type:"button",className:de.styles.next,attributes:{type:"button"},parent:e}));var n,r=i({className:de.styles.monthLabel,parent:e}),o=i({type:"table",className:de.styles.dayTable,parent:e}),a=i({type:"thead",className:de.styles.dayHead,parent:o}),s=i({type:"tr",className:de.styles.dayRow,parent:a}),u=i({type:"tbody",className:de.styles.dayBody,parent:o});for(n=0;he>n;n++)i({type:"th",className:de.styles.dayHeadElem,parent:s,text:pe[E(n)]});u.setAttribute(Me,t),Ce.push({label:r,body:u})}if(de.date){var e;for(Ce=[],xe=i({className:de.styles.date,parent:ye}),e=0;e<de.monthsInCalendar;e++)t(e);m.add(ke,"click",V),m.add(Ee,"click",B),m.add(xe,"click",re)}}function k(){if(de.time&&de.timeInterval){var t=i({className:de.styles.time,parent:ye});Fe=i({className:de.styles.selectedTime,parent:t,text:fe.format(de.timeFormat)}),m.add(Fe,"click",A),Ae=i({className:de.styles.timeList,parent:t}),m.add(Ae,"click",se);for(var e=d.moment("00:00:00","HH:mm:ss"),n=e.clone().add(1,"days")
;e.isBefore(n);)i({className:de.styles.timeOption,parent:Ae,text:e.format(de.timeFormat)}),e.add(de.timeInterval,"seconds")}}function E(t,e){var n=e?-1:1,r=t+de.weekStart*n;return(r>=he||0>r)&&(r+=he*-n),r}function F(){if(de.time&&De){var t,e,n,r,o=Ae.children,a=o.length;for(r=0;a>r;r++)n=o[r],e=d.moment(s(n),de.timeFormat),t=ie(fe.clone(),e),n.style.display=U(t,!1,de.timeValidator)?"block":"none"}}function A(t){var e="boolean"==typeof t?t:"none"===Ae.style.display;e?T():D()}function T(){Ae&&(Ae.style.display="block")}function D(){Ae&&(Ae.style.display="none")}function M(){ye.style.display="inline-block",Te.emit("show")}function C(){ye.style.display="none",Te.emit("hide")}function N(){return g(),$(),A(!de.date),M(),Te}function O(){return D(),a(C),Te}function I(){D();var t=f.contains(ye,de.styles.positioned);return t&&a(C),Te}function j(t){var e=t.target;if(e===Te.associated)return!0;for(;e;){if(e===ye)return!0;e=e.parentNode}}function H(t){j(t)||I()}function S(t){j(t)||I()}function
V(){L("subtract")}function B(){L("add")}function L(t){var e,n="add"===t?-1:1,r=de.monthsInCalendar+n*ae(ge);me[t](r,"months"),e=te(me.clone()),fe=e||fe,e&&(me=e.clone()),q()}function q(t){P(),W(),t!==!0&&z(),F()}function P(){function t(t,e){var n=me.clone().add(e,"months");s(t.label,n.format(de.monthFormat)),J(t.body)}if(de.date&&De){var e=me.year(),n=me.month(),r=me.date();if(r!==be||n!==we||e!==ve){var o=R();if(be=me.date(),we=me.month(),ve=me.year(),o)return Y(),void 0;Ce.forEach(t),K()}}}function Y(){function t(t){var e,n=[];for(e=0;e<t.length;e++)n.push(t[e]);return n}function e(e){return t(e.children)}function n(t){return!f.contains(t,de.styles.dayPrevMonth)&&!f.contains(t,de.styles.dayNextMonth)}var r=me.date()-1;oe(!1),Ce.forEach(function(o){var a;_(o.date,me)&&(a=t(o.body.children).map(e),a=Array.prototype.concat.apply([],a).filter(n),oe(a[r]))})}function R(){function t(t){return ve?_(t.date,me):!1}return Ce.some(t)}function _(t,e){return t&&e&&t.year()===e.year()&&t.month(
)===e.month()}function W(){de.time&&De&&s(Fe,fe.format(de.timeFormat))}function z(){return Te.emit("data",ce()),Te.emit("year",fe.year()),Te.emit("month",fe.month()),Te.emit("day",fe.day()),Te.emit("time",fe.format(de.timeFormat)),Te}function $(){return ve=!1,we=!1,be=!1,q(!0),Te}function G(t){var e=u(t,de.inputFormat);if(null!==e)return fe=te(e)||fe,me=fe.clone(),q(!0),Te}function J(t,e){for(;t&&t.firstChild;)t.removeChild(t.firstChild);e===!0&&t.parentNode.removeChild(t)}function K(){var t;for(t=0;t<de.monthsInCalendar;t++)Q(t)}function Q(t){function e(t){var e,r,o;for(e=0;e<t.length;e++)f.children.length===he&&(f=i({type:"tr",className:de.styles.dayRow,parent:a.body})),r=t.base.clone().add(e,"days"),o=i({type:"td",parent:f,text:r.format(de.dayFormat),className:n(r,t.cell.join(" ").split(" ")).join(" ")}),t.selectable&&r.date()===c&&oe(o)}function n(t,e){return U(t,!0,de.dateValidator)||e.push(p),e}function r(t,e){return t&&e.push(de.styles.dayConcealed),e}var o,a=Ce[t],s=me.clone
().add(t,"months"),u=s.daysInMonth(),c=s.month()!==fe.month()?-1:fe.date(),l=s.clone().date(1),d=E(l.day(),!0),f=i({type:"tr",className:de.styles.dayRow,parent:a.body}),m=r(0!==t,[de.styles.dayBodyElem,de.styles.dayPrevMonth]),y=r(t!==de.monthsInCalendar-1,[de.styles.dayBodyElem,de.styles.dayNextMonth]),p=de.styles.dayDisabled;e({base:l.clone().subtract(d,"days"),length:d,cell:m}),e({base:l.clone(),length:u,cell:[de.styles.dayBodyElem],selectable:!0}),o=l.clone().add(u,"days"),e({base:o,length:he-f.children.length,cell:y}),ke.disabled=!X(l,!0),Ee.disabled=!Z(o,!0),a.date=s.clone()}function U(t,e,n){if(!X(t,e))return!1;if(!Z(t,e))return!1;var r=(n||Function.prototype).call(Te,t.toDate());return r!==!1}function X(t,e){var n=de.min?e?de.min.clone().startOf("day"):de.min:!1;return!n||!t.isBefore(n)}function Z(t,e){var n=de.max?e?de.max.clone().endOf("day"):de.max:!1;return!n||!t.isAfter(n)}function te(t){if(de.min&&t.isBefore(de.min))return te(de.min.clone());if(de.max&&t.isAfter(de.max
))return te(de.max.clone());var e=t.clone().subtract(1,"days");return ne(e,t,"add")?ee(e):(e=t.clone(),ne(e,t,"subtract")?ee(e):void 0)}function ee(t){var e,n=t.clone().subtract(de.timeInterval,"seconds"),r=Math.ceil(Ne/de.timeInterval);for(e=0;r>e;e++)if(n.add(de.timeInterval,"seconds"),n.date()>t.date()&&n.subtract(1,"days"),de.timeValidator.call(Te,n.toDate())!==!1)return n}function ne(t,e,n){for(var r=!1;r===!1&&(t[n](1,"days"),t.month()===e.month());)r=de.dateValidator.call(Te,t.toDate());return r!==!1}function re(t){var e=t.target;if(!f.contains(e,de.styles.dayDisabled)&&f.contains(e,de.styles.dayBodyElem)){var n=parseInt(s(e),10),r=f.contains(e,de.styles.dayPrevMonth),o=f.contains(e,de.styles.dayNextMonth),a=ae(e)-ae(ge);fe.add(a,"months"),(r||o)&&fe.add(r?-1:1,"months"),oe(e),fe.date(n),ie(fe,te(fe)||fe),me=fe.clone(),de.autoClose===!0&&I(),q()}}function oe(t){ge&&f.remove(ge,de.styles.selectedDay),t&&f.add(t,de.styles.selectedDay),ge=t}function ae(t){for(var e;t&&t.getAttri
bute;){if(e=t.getAttribute(Me),"string"==typeof e)return parseInt(e,10);t=t.parentNode}return 0}function ie(t,e){return t.hour(e.hour()).minute(e.minute()).second(e.second()),t}function se(t){var e=t.target;if(f.contains(e,de.styles.timeOption)){var n=d.moment(s(e),de.timeFormat);ie(fe,n),me=fe.clone(),z(),W(),!de.date&&de.autoClose===!0||"time"===de.autoClose?I():D()}}function ue(){return fe.toDate()}function ce(t){return fe.format(t||de.inputFormat)}function le(){return fe.clone()}var de,fe,me,ye,pe,he,ve,we,be,ge,xe,ke,Ee,Fe,Ae,Te=o({}),De=!1,Me="data-rome-offset",Ce=[],Ne=86400;return n(),a(p),Te}var r,o=t("contra.emitter"),a=t("raf"),i=t("./dom"),s=t("./text"),u=t("./parse"),c=t("./clone"),l=t("./defaults"),d=t("./momentum"),f=t("./classes"),m=t("./events"),y=t("./noop");e.exports=n},{"./classes":8,"./clone":9,"./defaults":11,"./dom":12,"./events":13,"./momentum":18,"./noop":19,"./parse":20,"./text":32,"contra.emitter":2,raf:4}],8:[function(t,e){"use strict";function n(t){retur
n t.className.replace(s,"").split(u)}function r(t,e){t.className=e.join(" ")}function o(t,e){var n=a(t,e);n.push(e),r(t,n)}function a(t,e){var o=n(t),a=o.indexOf(e);return-1!==a&&(o.splice(a,1),r(t,o)),o}function i(t,e){return-1!==n(t).indexOf(e)}var s=/^\s+|\s+$/g,u=/\s+/;e.exports={add:o,remove:a,contains:i}},{}],9:[function(t,e){"use strict";function n(t){var e,o={};for(var a in t)e=t[a],o[a]=e?r.isMoment(e)?e.clone():e._isStylesConfiguration?n(e):e:e;return o}var r=t("./momentum");e.exports=n},{"./momentum":18}],10:[function(t,e){"use strict";function n(t,e){var n,s=r.find(t);return s?s:(n=i(t)?o(t,e):a(t,e),n.associated=t,r.assign(t,n),n)}var r=t("./index"),o=t("./input"),a=t("./inline"),i=t("./isInput");e.exports=n},{"./index":14,"./inline":15,"./input":16,"./isInput":17}],11:[function(t,e){"use strict";function n(t,e){var n,i,s=t||{};if(s.autoHideOnClick===i&&(s.autoHideOnClick=!0),s.autoHideOnBlur===i&&(s.autoHideOnBlur=!0),s.autoClose===i&&(s.autoClose=!0),s.appendTo===i&&(
s.appendTo=document.body),"parent"===s.appendTo){if(!o(e.associated))throw new Error("Inline calendars must be appended to a parent node explicitly.");s.appendTo=e.associated.parentNode}if(s.invalidate===i&&(s.invalidate=!0),s.required===i&&(s.required=!1),s.date===i&&(s.date=!0),s.time===i&&(s.time=!0),s.date===!1&&s.time===!1)throw new Error("At least one of `date` or `time` must be `true`.");if(s.inputFormat===i&&(s.inputFormat=s.date&&s.time?"YYYY-MM-DD HH:mm":s.date?"YYYY-MM-DD":"HH:mm"),s.initialValue=s.initialValue===i?null:r(s.initialValue,s.inputFormat),s.min=s.min===i?null:r(s.min,s.inputFormat),s.max=s.max===i?null:r(s.max,s.inputFormat),s.timeInterval===i&&(s.timeInterval=1800),s.min&&s.max)if(s.max.isBefore(s.min)&&(n=s.max,s.max=s.min,s.min=n),s.date===!0){if(s.max.clone().subtract(1,"days").isBefore(s.min))throw new Error("`max` must be at least one day after `min`")}else if(1e3*s.timeInterval-s.min%(1e3*s.timeInterval)>s.max-s.min)throw new Error("`min` to `max` rang
e must allow for at least one time option that matches `timeInterval`");if(s.dateValidator===i&&(s.dateValidator=Function.prototype),s.timeValidator===i&&(s.timeValidator=Function.prototype),s.timeFormat===i&&(s.timeFormat="HH:mm"),s.weekStart===i&&(s.weekStart=a.moment().weekday(0).day()),s.weekdayFormat===i&&(s.weekdayFormat="min"),"long"===s.weekdayFormat)s.weekdayFormat=a.moment.weekdays();else if("short"===s.weekdayFormat)s.weekdayFormat=a.moment.weekdaysShort();else if("min"===s.weekdayFormat)s.weekdayFormat=a.moment.weekdaysMin();else if(!Array.isArray(s.weekdayFormat)||s.weekdayFormat.length<7)throw new Error("`weekdays` must be `min`, `short`, or `long`");s.monthsInCalendar===i&&(s.monthsInCalendar=1),s.monthFormat===i&&(s.monthFormat="MMMM YYYY"),s.dayFormat===i&&(s.dayFormat="DD"),s.styles===i&&(s.styles={}),s.styles._isStylesConfiguration=!0;var u=s.styles;return u.back===i&&(u.back="rd-back"),u.container===i&&(u.container="rd-container"),u.positioned===i&&(u.positioned=
"rd-container-attachment"),u.date===i&&(u.date="rd-date"),u.dayBody===i&&(u.dayBody="rd-days-body"),u.dayBodyElem===i&&(u.dayBodyElem="rd-day-body"),u.dayPrevMonth===i&&(u.dayPrevMonth="rd-day-prev-month"),u.dayNextMonth===i&&(u.dayNextMonth="rd-day-next-month"),u.dayDisabled===i&&(u.dayDisabled="rd-day-disabled"),u.dayConcealed===i&&(u.dayConcealed="rd-day-concealed"),u.dayHead===i&&(u.dayHead="rd-days-head"),u.dayHeadElem===i&&(u.dayHeadElem="rd-day-head"),u.dayRow===i&&(u.dayRow="rd-days-row"),u.dayTable===i&&(u.dayTable="rd-days"),u.month===i&&(u.month="rd-month"),u.monthLabel===i&&(u.monthLabel="rd-month-label"),u.next===i&&(u.next="rd-next"),u.selectedDay===i&&(u.selectedDay="rd-day-selected"),u.selectedTime===i&&(u.selectedTime="rd-time-selected"),u.time===i&&(u.time="rd-time"),u.timeList===i&&(u.timeList="rd-time-list"),u.timeOption===i&&(u.timeOption="rd-time-option"),s}var r=t("./parse"),o=t("./isInput"),a=t("./momentum");e.exports=n},{"./isInput":17,"./momentum":18,"./par
se":20}],12:[function(t,e){"use strict";function n(t){var e=t||{};e.type||(e.type="div");var n=document.createElement(e.type);return e.className&&(n.className=e.className),e.text&&(n.innerText=n.textContent=e.text),e.attributes&&Object.keys(e.attributes).forEach(function(t){n.setAttribute(t,e.attributes[t])}),e.parent&&e.parent.appendChild(n),n}e.exports=n},{}],13:[function(t,e){"use strict";function n(t,e,n,r){return t.addEventListener(e,n,r)}function r(t,e,n,r){return t.attachEvent("on"+e,function(e){var r=e||window.event;r.target=r.target||r.srcElement,r.preventDefault=r.preventDefault||function(){r.returnValue=!1},r.stopPropagation=r.stopPropagation||function(){r.cancelBubble=!0},n.call(t,r)},r)}function o(t,e,n){return t.removeEventListener(e,n)}function a(t,e,n){return t.detachEvent("on"+e,n)}var i=n,s=o;window.addEventListener||(i=r),window.removeEventListener||(s=a),e.exports={add:i,remove:s}},{}],14:[function(t,e){"use strict";function n(t){if("number"!=typeof t&&t&&t.getAt
tribute)return n(t.getAttribute(a));var e=i[t];return e!==o?e:null}function r(t,e){t.setAttribute(a,e.id=i.push(e)-1)}var o,a="data-rome-id",i=[];e.exports={find:n,assign:r}},{}],15:[function(t,e){"use strict";function n(t,e){var n=e||{};return n.appendTo=t,r(n)}var r=(t("raf"),t("./calendar"));e.exports=n},{"./calendar":7,raf:4}],16:[function(t,e){"use strict";function n(t,e){function n(n){x=a(n||e,F),u.add(F.container,x.styles.positioned),c.add(F.container,"mousedown",m),c.add(F.container,"click",f),F.getDate=g(F.getDate),F.getDateString=g(F.getDateString),F.getMoment=g(F.getMoment),x.initialValue&&(t.value=x.initialValue.format(x.inputFormat)),F.on("data",w),F.on("show",T),d(),A(),F.hide()}function l(){d(!0)}function d(e){var r=e?"remove":"add";c[r](t,"click",p),c[r](t,"touchend",p),c[r](t,"focusin",p),c[r](t,"change",A),c[r](t,"keypress",A),c[r](t,"keydown",A),c[r](t,"input",A),x.invalidate&&c[r](t,"blur",y),c[r](window,"resize",T),e?(F.once("ready",n),F.off("destroyed",l)):(F.o
ff("ready",n),F.once("destroyed",l))}function f(){E=!0,t.focus(),E=!1}function m(){function t(){k=!1}k=!0,o(t)}function y(){k||b()||F.emitValues()}function p(){E||F.show()}function h(){var e=t.getBoundingClientRect(),n=document.body.scrollTop||document.documentElement.scrollTop;F.container.style.top=e.top+n+t.offsetHeight+"px",F.container.style.left=e.left+"px"}function v(){var e=t.value.trim();if(!b()){var n=s.moment(e,x.inputFormat,x.strictParse);F.setValue(n)}}function w(e){t.value=e}function b(){return x.required===!1&&""===t.value.trim()}function g(t){return function(){return b()?null:t.apply(this,arguments)}}var x,k,E,F=i(e),A=r(v,30),T=r(h,30);return n(e),F}var r=t("./throttle"),o=t("raf"),a=(t("./clone"),t("./defaults")),i=t("./calendar"),s=t("./momentum"),u=t("./classes"),c=t("./events");e.exports=n},{"./calendar":7,"./classes":8,"./clone":9,"./defaults":11,"./events":13,"./momentum":18,"./throttle":33,raf:4}],17:[function(t,e){"use strict";function n(t){return t&&t.nodeNam
e&&"input"===t.nodeName.toLowerCase()}e.exports=n},{}],18:[function(t,e){"use strict";function n(t){return t&&Object.prototype.hasOwnProperty.call(t,"_isAMomentObject")}var r={moment:null,isMoment:n};e.exports=r},{}],19:[function(t,e){"use strict";function n(){}e.exports=n},{}],20:[function(t,e){"use strict";function n(t,e){return"string"==typeof t?o.moment(t,e):"[object Date]"===Object.prototype.toString.call(t)?o.moment(t):o.isMoment(t)?t.clone():void 0}function r(t,e){var r=n(t,"string"==typeof e?e:null);return r&&r.isValid()?r:null}var o=t("./momentum");e.exports=r},{"./momentum":18}],21:[function(){"use strict";Array.prototype.filter||(Array.prototype.filter=function(t,e){var n=[];return this.forEach(function(r,o,a){t.call(e,r,o,a)&&n.push(r)},e),n})},{}],22:[function(){"use strict";Array.prototype.forEach||(Array.prototype.forEach=function(t,e){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var n=this,r=n.length,o=0;r>o;o++)o in n&&t.call(e,n[o],o,
n)})},{}],23:[function(){"use strict";Array.prototype.indexOf||(Array.prototype.indexOf=function(t,e){if(void 0===this||null===this)throw new TypeError;var n=this.length;for(e=+e||0,1/0===Math.abs(e)?e=0:0>e&&(e+=n,0>e&&(e=0));n>e;e++)if(this[e]===t)return e;return-1})},{}],24:[function(){"use strict";Array.isArray||(Array.isArray=function(t){return""+t!==t&&"[object Array]"===Object.prototype.toString.call(t)})},{}],25:[function(){"use strict";Array.prototype.map||(Array.prototype.map=function(t,e){var n,r,o;if(null==this)throw new TypeError("this is null or not defined");var a=Object(this),i=a.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),r=new Array(i),o=0;i>o;)o in a&&(r[o]=t.call(n,a[o],o,a)),o++;return r})},{}],26:[function(){"use strict";Array.prototype.some||(Array.prototype.some=function(t,e){var n,r;if(null==this)throw new TypeError("this is null or not defined");var o=Object(this),a=o.length>>>0;if("function"!
=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),r=0;a>r;){if(r in o){var i=t.call(n,o[r],r,o);if(i)return!0}r++}return!1})},{}],27:[function(){"use strict";Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),n=this,r=function(){},o=function(){var o=this instanceof r&&t?this:t,a=e.concat(Array.prototype.slice.call(arguments));return n.apply(o,a)};return r.prototype=this.prototype,o.prototype=new r,o})},{}],28:[function(){"use strict";var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=n.length;Object.keys||(Object.keys=function(o){if("object"!=typeof o&&("function"!=typeof o||null===o))throw new TypeError("Object.keys called on
non-object");var a,i,s=[];for(a in o)t.call(o,a)&&s.push(a);if(e)for(i=0;r>i;i++)t.call(o,n[i])&&s.push(n[i]);return s})},{}],29:[function(){"use strict";String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")})},{}],30:[function(t,e){"use strict";t("./polyfills/function.bind"),t("./polyfills/array.foreach"),t("./polyfills/array.map"),t("./polyfills/array.filter"),t("./polyfills/array.isarray"),t("./polyfills/array.indexof"),t("./polyfills/array.some"),t("./polyfills/string.trim"),t("./polyfills/object.keys");var n=t("./core"),r=t("./index"),o=t("./use");n.use=o.bind(n),n.find=r.find,n.val=t("./validators"),e.exports=n},{"./core":10,"./index":14,"./polyfills/array.filter":21,"./polyfills/array.foreach":22,"./polyfills/array.indexof":23,"./polyfills/array.isarray":24,"./polyfills/array.map":25,"./polyfills/array.some":26,"./polyfills/function.bind":27,"./polyfills/object.keys":28,"./polyfills/string.trim":29,"./use":34,"./validators":35}],31:[fu
nction(t,e){(function(n){var r=t("./rome"),o=t("./momentum");if(r.use(n.moment),void 0===o.moment)throw new Error("rome depends on moment.js, you can get it at http://momentjs.com, or you could use the bundled distribution file instead.");e.exports=r}).call(this,"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./momentum":18,"./rome":30}],32:[function(t,e){"use strict";function n(t,e){return 2===arguments.length&&(t.innerText=t.textContent=e),t.innerText||t.textContent}e.exports=n},{}],33:[function(t,e){"use strict";e.exports=function(t,e){var n,r=-1/0;return function(){function o(){clearTimeout(n),n=null;var a=r+e,i=Date.now();i>a?(r=i,t.apply(this,arguments)):n=setTimeout(o,a-i)}n||o()}}},{}],34:[function(t,e){"use strict";function n(t){this.moment=r.moment=t}var r=t("./momentum");e.exports=n},{"./momentum":18}],35:[function(t,e){"use strict";function n(t){return function(e){var n=a(e);return function(r){var s=o.find(e),u=a(r),c=n||s&&s.getMoment();return c?(
s&&i.add(this,s),t(u,c)):!0}}}function r(t,e){return function(n,r){function s(t){var e,n,r=o.find(t);return r?e=n=r.getMoment():Array.isArray(t)?(e=t[0],n=t[1]):e=n=t,r&&i.add(r,this),{start:a(e).startOf("day").toDate(),end:a(n).endOf("day").toDate()}}var u,c=arguments.length;return Array.isArray(n)?u=n:1===c?u=[n]:2===c&&(u=[[n,r]]),function(n){return u.map(s.bind(this))[t](e.bind(this,n))}}}var o=t("./index"),a=t("./parse"),i=t("./association"),s=n(function(t,e){return t>=e}),u=n(function(t,e){return t>e}),c=n(function(t,e){return e>=t}),l=n(function(t,e){return e>t}),d=r("every",function(t,e){return e.start>t||e.end<t}),f=r("some",function(t,e){return e.start<=t&&e.end>=t});e.exports={afterEq:s,after:u,beforeEq:c,before:l,except:d,only:f}},{"./association":6,"./index":14,"./parse":20}]},{},[31])(31)});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/underscore-1.7.0.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/underscore-1.7.0.js b/htrace-htraced/src/web/lib/underscore-1.7.0.js
new file mode 100644
index 0000000..d5b3375
--- /dev/null
+++ b/htrace-htraced/src/web/lib/underscore-1.7.0.js
@@ -0,0 +1,1416 @@
+// Underscore.js 1.7.0
+// http://underscorejs.org
+// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `exports` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ concat = ArrayProto.concat,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.7.0';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var createCallback = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ _.iteratee = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return createCallback(value, context, argCount);
+ if (_.isObject(value)) return _.matches(value);
+ return _.property(value);
+ };
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
+ if (obj == null) return obj;
+ iteratee = createCallback(iteratee, context);
+ var i, length = obj.length;
+ if (length === +length) {
+ for (i = 0; i < length; i++) {
+ iteratee(obj[i], i, obj);
+ }
+ } else {
+ var keys = _.keys(obj);
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
+ }
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ if (obj == null) return [];
+ iteratee = _.iteratee(iteratee, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length),
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
+ return results;
+ };
+
+ var reduceError = 'Reduce of empty array with no initial value';
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
+ if (obj == null) obj = [];
+ iteratee = createCallback(iteratee, context, 4);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index = 0, currentKey;
+ if (arguments.length < 3) {
+ if (!length) throw new TypeError(reduceError);
+ memo = obj[keys ? keys[index++] : index++];
+ }
+ for (; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
+ if (obj == null) obj = [];
+ iteratee = createCallback(iteratee, context, 4);
+ var keys = obj.length !== + obj.length && _.keys(obj),
+ index = (keys || obj).length,
+ currentKey;
+ if (arguments.length < 3) {
+ if (!index) throw new TypeError(reduceError);
+ memo = obj[keys ? keys[--index] : --index];
+ }
+ while (index--) {
+ currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
+ }
+ return memo;
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, predicate, context) {
+ var result;
+ predicate = _.iteratee(predicate, context);
+ _.some(obj, function(value, index, list) {
+ if (predicate(value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, predicate, context) {
+ var results = [];
+ if (obj == null) return results;
+ predicate = _.iteratee(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, predicate, context) {
+ return _.filter(obj, _.negate(_.iteratee(predicate)), context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, predicate, context) {
+ if (obj == null) return true;
+ predicate = _.iteratee(predicate, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index, currentKey;
+ for (index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Aliased as `any`.
+ _.some = _.any = function(obj, predicate, context) {
+ if (obj == null) return false;
+ predicate = _.iteratee(predicate, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index, currentKey;
+ for (index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
+ };
+
+ // Determine if the array or object contains a given value (using `===`).
+ // Aliased as `include`.
+ _.contains = _.include = function(obj, target) {
+ if (obj == null) return false;
+ if (obj.length !== +obj.length) obj = _.values(obj);
+ return _.indexOf(obj, target) >= 0;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ return (isFunc ? method : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, _.property(key));
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs) {
+ return _.filter(obj, _.matches(attrs));
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.find(obj, _.matches(attrs));
+ };
+
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = obj.length === +obj.length ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = obj.length === +obj.length ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
+ }
+ } else {
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
+ return result;
+ };
+
+ // Shuffle a collection, using the modern version of the
+ // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+ _.shuffle = function(obj) {
+ var set = obj && obj.length === +obj.length ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
+ return shuffled;
+ };
+
+ // Sample **n** random values from a collection.
+ // If **n** is not specified, returns a single random element.
+ // The internal `guard` argument allows it to work with `map`.
+ _.sample = function(obj, n, guard) {
+ if (n == null || guard) {
+ if (obj.length !== +obj.length) obj = _.values(obj);
+ return obj[_.random(obj.length - 1)];
+ }
+ return _.shuffle(obj).slice(0, Math.max(0, n));
+ };
+
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = _.iteratee(iteratee, context);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value: value,
+ index: index,
+ criteria: iteratee(value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index - right.index;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(behavior) {
+ return function(obj, iteratee, context) {
+ var result = {};
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
+ });
+ return result;
+ };
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
+ });
+
+ // Indexes the object's values by a criterion, similar to `groupBy`, but for
+ // when you know that your index values will be unique.
+ _.indexBy = group(function(result, value, key) {
+ result[key] = value;
+ });
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
+ });
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = _.iteratee(iteratee, context, 1);
+ var value = iteratee(obj);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = low + high >>> 1;
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+ }
+ return low;
+ };
+
+ // Safely create a real, live array from anything iterable.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (obj.length === +obj.length) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return obj.length === +obj.length ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = _.iteratee(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[0];
+ if (n < 0) return [];
+ return slice.call(array, 0, n);
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if (n == null || guard) return array[array.length - 1];
+ return slice.call(array, Math.max(array.length - n, 0));
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, n == null || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, strict, output) {
+ if (shallow && _.every(input, _.isArray)) {
+ return concat.apply(output, input);
+ }
+ for (var i = 0, length = input.length; i < length; i++) {
+ var value = input[i];
+ if (!_.isArray(value) && !_.isArguments(value)) {
+ if (!strict) output.push(value);
+ } else if (shallow) {
+ push.apply(output, value);
+ } else {
+ flatten(value, shallow, strict, output);
+ }
+ }
+ return output;
+ };
+
+ // Flatten out an array, either recursively (by default), or just one level.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, false, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (array == null) return [];
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
+ isSorted = false;
+ }
+ if (iteratee != null) iteratee = _.iteratee(iteratee, context);
+ var result = [];
+ var seen = [];
+ for (var i = 0, length = array.length; i < length; i++) {
+ var value = array[i];
+ if (isSorted) {
+ if (!i || seen !== value) result.push(value);
+ seen = value;
+ } else if (iteratee) {
+ var computed = iteratee(value, i, array);
+ if (_.indexOf(seen, computed) < 0) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (_.indexOf(result, value) < 0) {
+ result.push(value);
+ }
+ }
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(flatten(arguments, true, true, []));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ if (array == null) return [];
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = array.length; i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = flatten(slice.call(arguments, 1), true, true, []);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function(array) {
+ if (array == null) return [];
+ var length = _.max(arguments, 'length').length;
+ var results = Array(length);
+ for (var i = 0; i < length; i++) {
+ results[i] = _.pluck(arguments, i);
+ }
+ return results;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ if (list == null) return {};
+ var result = {};
+ for (var i = 0, length = list.length; i < length; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i = 0, length = array.length;
+ if (isSorted) {
+ if (typeof isSorted == 'number') {
+ i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
+ } else {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ }
+ for (; i < length; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ _.lastIndexOf = function(array, item, from) {
+ if (array == null) return -1;
+ var idx = array.length;
+ if (typeof from == 'number') {
+ idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
+ }
+ while (--idx >= 0) if (array[idx] === item) return idx;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Reusable constructor function for prototype setting.
+ var Ctor = function(){};
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ var args, bound;
+ if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
+ args = slice.call(arguments, 2);
+ bound = function() {
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
+ Ctor.prototype = func.prototype;
+ var self = new Ctor;
+ Ctor.prototype = null;
+ var result = func.apply(self, args.concat(slice.call(arguments)));
+ if (_.isObject(result)) return result;
+ return self;
+ };
+ return bound;
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context. _ acts
+ // as a placeholder, allowing any combination of arguments to be pre-filled.
+ _.partial = function(func) {
+ var boundArgs = slice.call(arguments, 1);
+ return function() {
+ var position = 0;
+ var args = boundArgs.slice();
+ for (var i = 0, length = args.length; i < length; i++) {
+ if (args[i] === _) args[i] = arguments[position++];
+ }
+ while (position < arguments.length) args.push(arguments[position++]);
+ return func.apply(this, args);
+ };
+ };
+
+ // Bind a number of an object's methods to that object. Remaining arguments
+ // are the method names to be bound. Useful for ensuring that all callbacks
+ // defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = hasher ? hasher.apply(this, arguments) : key;
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
+ };
+ memoize.cache = {};
+ return memoize;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time. Normally, the throttled function will run
+ // as much as it can, without ever going more than once per `wait` duration;
+ // but if you'd like to disable the execution on the leading edge, pass
+ // `{leading: false}`. To disable execution on the trailing edge, ditto.
+ _.throttle = function(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ if (!options) options = {};
+ var later = function() {
+ previous = options.leading === false ? 0 : _.now();
+ timeout = null;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ };
+ return function() {
+ var now = _.now();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0 || remaining > wait) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
+ var later = function() {
+ var last = _.now() - timestamp;
+
+ if (last < wait && last > 0) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ if (!timeout) context = args = null;
+ }
+ }
+ };
+
+ return function() {
+ context = this;
+ args = arguments;
+ timestamp = _.now();
+ var callNow = immediate && !timeout;
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+
+ return result;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return _.partial(wrapper, func);
+ };
+
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var args = arguments;
+ var start = args.length - 1;
+ return function() {
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Returns a function that will only be executed before being called N times.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ } else {
+ func = null;
+ }
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = function(obj) {
+ if (!_.isObject(obj)) return [];
+ if (nativeKeys) return nativeKeys(obj);
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys.push(key);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var values = Array(length);
+ for (var i = 0; i < length; i++) {
+ values[i] = obj[keys[i]];
+ }
+ return values;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var keys = _.keys(obj);
+ var length = keys.length;
+ var pairs = Array(length);
+ for (var i = 0; i < length; i++) {
+ pairs[i] = [keys[i], obj[keys[i]]];
+ }
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ var keys = _.keys(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ result[obj[keys[i]]] = keys[i];
+ }
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ var source, prop;
+ for (var i = 1, length = arguments.length; i < length; i++) {
+ source = arguments[i];
+ for (prop in source) {
+ if (hasOwnProperty.call(source, prop)) {
+ obj[prop] = source[prop];
+ }
+ }
+ }
+ return obj;
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(obj, iteratee, context) {
+ var result = {}, key;
+ if (obj == null) return result;
+ if (_.isFunction(iteratee)) {
+ iteratee = createCallback(iteratee, context);
+ for (key in obj) {
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ } else {
+ var keys = concat.apply([], slice.call(arguments, 1));
+ obj = new Object(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (key in obj) result[key] = obj[key];
+ }
+ }
+ return result;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
+ }
+ return _.pick(obj, iteratee, context);
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ for (var i = 1, length = arguments.length; i < length; i++) {
+ var source = arguments[i];
+ for (var prop in source) {
+ if (obj[prop] === void 0) obj[prop] = source[prop];
+ }
+ }
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className !== toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return '' + a === '' + b;
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a === +b;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] === a) return bStack[length] === b;
+ }
+ // Objects with different constructors are not equivalent, but `Object`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (
+ aCtor !== bCtor &&
+ // Handle Object.create(x) cases
+ 'constructor' in a && 'constructor' in b &&
+ !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ ) {
+ return false;
+ }
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+ var size, result;
+ // Recursively compare objects and arrays.
+ if (className === '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size === b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+ }
+ }
+ } else {
+ // Deep compare objects.
+ var keys = _.keys(a), key;
+ size = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ result = _.keys(b).length === size;
+ if (result) {
+ while (size--) {
+ // Deep compare each member
+ key = keys[size];
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+ }
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return result;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, [], []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) === '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return _.has(obj, 'callee');
+ };
+ }
+
+ // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
+ if (typeof /./ !== 'function') {
+ _.isFunction = function(obj) {
+ return typeof obj == 'function' || false;
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iteratees.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Predicate-generating functions. Often useful outside of Underscore.
+ _.constant = function(value) {
+ return function() {
+ return value;
+ };
+ };
+
+ _.noop = function(){};
+
+ _.property = function(key) {
+ return function(obj) {
+ return obj[key];
+ };
+ };
+
+ // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
+ _.matches = function(attrs) {
+ var pairs = _.pairs(attrs), length = pairs.length;
+ return function(obj) {
+ if (obj == null) return !length;
+ obj = new Object(obj);
+ for (var i = 0; i < length; i++) {
+ var pair = pairs[i], key = pair[0];
+ if (pair[1] !== obj[key] || !(key in obj)) return false;
+ }
+ return true;
+ };
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iteratee, context) {
+ var accum = Array(Math.max(0, n));
+ iteratee = createCallback(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // A (possibly faster) way to get the current timestamp as an integer.
+ _.now = Date.now || function() {
+ return new Date().getTime();
+ };
+
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
+ };
+ var unescapeMap = _.invert(escapeMap);
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
+ };
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
+
+ // If the value of the named `property` is a function then invoke it with the
+ // `object` as context; otherwise, return it.
+ _.result = function(object, property) {
+ if (object == null) return void 0;
+ var value = object[property];
+ return _.isFunction(value) ? object[property]() : value;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ } else if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ } else if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+
+ // Adobe VMs need the match returned to produce the correct offest.
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + 'return __p;\n';
+
+ try {
+ var render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
+ _.chain = function(obj) {
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj) {
+ return this._chain ? _(obj).chain() : obj;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result.call(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
+ return result.call(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result.call(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
+
+ // AMD registration happens at the end for compatibility with AMD loaders
+ // that may not enforce next-turn semantics on modules. Even though general
+ // practice for AMD registration is to be anonymous, underscore registers
+ // as a named module because, like jQuery, it is a base library that is
+ // popular enough to be bundled in a third party lib, but not be part of
+ // an AMD load request. Those cases could generate an error when an
+ // anonymous define() is called outside of a loader request.
+ if (typeof define === 'function' && define.amd) {
+ define('underscore', [], function() {
+ return _;
+ });
+ }
+}.call(this));
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index db31d6c..83c38d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,15 +164,12 @@ language governing permissions and limitations under the License. -->
<exclude>style.txt</exclude>
<!-- external projects -->
<exclude>**/bootstrap-3.3.1/**</exclude>
- <exclude>**/web/lib/js/**</exclude>
- <exclude>**/web/lib/css/**</exclude>
- <exclude>**/web/lib/rome-2.1.0/**</exclude>
+ <exclude>**/web/lib/**</exclude>
<exclude>**/*.min.js</exclude>
<exclude>**/d3.min.js</exclude>
<!-- Pulled down sources -->
- <exclude>**/gopkg.in/**</exclude>
- <exclude>**/github.com/**</exclude>
- <exclude>**/golang.org/**</exclude>
+ <exclude>**/build/src/**</exclude>
+ <exclude>**/build/pkg/**</exclude>
<exclude>**/Godeps/**</exclude>
</excludes>
</configuration>
[17/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/views/search/field.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/views/search/field.js b/htrace-htraced/src/web/app/views/search/field.js
deleted file mode 100644
index c9f048a..0000000
--- a/htrace-htraced/src/web/app/views/search/field.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-app.SearchFieldView = Backbone.View.extend({
- 'className': 'search-field',
-
- 'template': _.template($("#search-field-template").html()),
-
- 'events': {
- 'change .field': 'showSearchField',
- 'click .remove-field': 'destroyField'
- },
-
- 'initialize': function(options) {
- this.options = options;
- this.field = options.field;
- },
-
- 'render': function() {
- this.$el.html(this.template({ field: this.field }));
- this.showSearchField();
- if (this.options.value) this.setValue();
- return this;
- },
-
- 'showSearchField': function() {
- // this.$el.find('.value').hide();
- // this.$el.find('.op').hide();
- // this.$el.find('label').hide();
- this.$el.find('.search-field').hide();
- switch (this.field) {
- case 'begin':
- case 'end':
- this.$el.find('.op').show();
- this.$el.find('.start-end-date-time').show();
- this.$el.find('label.start-end-date-time').text(this.field === 'begin' ? 'Begin' : 'End');
- rome(this.$el.find('#start-end-date-time')[0]);
- break;
- case 'duration':
- this.op = 'ge'
- this.$el.find('.duration').show();
- break;
- case 'description':
- this.op = 'cn'
- this.$el.find('.description').show();
- break;
- default:
- break;
- }
- },
-
- 'destroyField': function(e) {
- this.undelegateEvents();
-
- $(this.el).removeData().unbind();
-
- this.remove();
- Backbone.View.prototype.remove.call(this);
- this.options.manager.trigger('removeSearchField', [this.cid]);
- },
-
- 'addPredicate': function() {
- this.options.predicates.push(
- {
- 'op': this.op ? this.op : this.$('.op:visible').val(),
- 'field': this.field,
- 'val': this.getValue()
- }
- );
- },
-
- 'getPredicate': function() {
- return {
- 'op': this.op ? this.op : this.$('.op:visible').val(),
- 'field': this.field,
- 'val': this.getValue()
- };
- },
-
- 'getValue': function() {
- switch (this.field) {
- case 'begin':
- case 'end':
- var now = new moment();
- var datetime = new moment(this.$('input.start-end-date-time:visible').val()).unix();
- return datetime.toString();
- case 'duration':
- return this.$("input.duration:visible").val().toString();
- case 'description':
- return this.$('input.description').val();
- default:
- return '';
- }
- },
-
- 'setValue': function() {
- switch (this.field) {
- case 'begin':
- case 'end':
- this.$('select.op').val(this.options.op);
- this.$('input.start-end-date-time').val(moment.unix(this.options.value).format('YYYY-MM-DD HH:mm'));
- case 'duration':
- this.$("input.duration").val(this.options.value);
- case 'description':
- this.$('input.description').val(this.options.value);
- }
- }
-});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/views/search/search.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/views/search/search.js b/htrace-htraced/src/web/app/views/search/search.js
deleted file mode 100644
index b9acee5..0000000
--- a/htrace-htraced/src/web/app/views/search/search.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-app.SearchView = Backbone.Marionette.LayoutView.extend({
- "template": "#search-layout-template",
- "regions": {
- "controls": "div[role='form']",
- "main": "div[role='main']",
- "pagination": "div[role='complementary']"
- }
-});
-
-app.SearchControlsView = Backbone.Marionette.View.extend({
- "template": _.template($("#search-controls-template").html()),
- "events": {
- "click a.add-field": "addSearchField",
- "click button.search": "search",
- },
-
- "initialize": function(options) {
- this.options = options;
- this.predicates = [];
- this.searchFields = [];
- this.searchFields.push(new app.SearchFieldView({
- predicates: this.predicates,
- manager: this,
- field: 'description'
- }));
- this.on('removeSearchField', this.removeSearchField, this);
- },
-
- "render": function() {
- this.$el.html(this.template());
- this.$el.find('.search-fields').append(this.searchFields[0].render().$el);
-
- _(this.options.predicates).each(function(pred) {
- if (pred.field === 'description') {
- this.$el.find('input.description').val(pred.val);
- } else {
- this.addSearchField(pred);
- }
- }.bind(this));
-
- return this;
- },
-
- "addSearchField": function(e) {
- var target = e.target ? $(e.target) : e;
- if (e.target) $('button.field').text(target.text());
- var searchOptions = {
- predicates: this.predicates,
- manager: this,
- field: target.data ? target.data('field') : target.field,
- };
- if (!e.target) _.extend(searchOptions, { value: target.val, op: target.op})
-
- var newSearchField = new app.SearchFieldView(searchOptions);
- this.$el.find('.search-fields').append(newSearchField.render().$el);
- this.searchFields.push(newSearchField);
- },
-
- "removeSearchField": function(cid) {
- var removedFieldIndex = _(this.searchFields).indexOf(_(this.searchFields).findWhere({cid: cid}));
- this.searchFields.splice(removedFieldIndex, 1);
- },
-
- "search": function(e) {
- this.predicates = _(this.searchFields).map(function(field) {
- return field.getPredicate();
- }).filter(function(predicate) {
- return predicate.val;
- });
-
- this.searchParams = _(this.predicates).map(function(predicate) {
- return $.param(predicate);
- }).join(';');
- Backbone.history.navigate('!/search?' + this.searchParams, { trigger: false });
-
- this.collection.switchMode("infinite", {
- fetch: false,
- resetState: true
- });
-
- this.collection.fullCollection.reset();
- this.collection.setPredicates(this.predicates);
- this.collection.fetch();
- return false;
- }
-});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/views/swimlane/swimlane.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/views/swimlane/swimlane.js b/htrace-htraced/src/web/app/views/swimlane/swimlane.js
deleted file mode 100644
index 99f0b88..0000000
--- a/htrace-htraced/src/web/app/views/swimlane/swimlane.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-app.SwimlaneView = Backbone.Marionette.LayoutView.extend({
- "template": "#swimlane-layout-template",
- "regions": {
- "swimlane": "div[role='main']",
- }
-});
-
-app.SwimlaneGraphView = Backbone.Marionette.View.extend({
- className: "swimlane",
-
- initialize: function() {
- this.spans = this.getSpans(0, [],
- this.getJsonSync("/span/" + this.options.spanId),
- this.options.lim || "lim=100",
- this.getJsonSync);
- },
-
- onShow: function() {
- this.appendSVG(this.spans);
- },
-
- getSpans: function getSpans(depth, spans, span, lim, getJSON) {
- span.depth = depth;
- spans.push(span);
- var children = [];
- getJSON("/span/" + span.s + "/children?" + lim).forEach(function(childId) {
- children.push(getJSON("/span/" + childId));
- });
- children.sort(function(x, y) {
- return x.b < y.b ? -1 : x.b > y.b ? 1 : 0;
- });
- children.forEach(function(child) {
- spans = getSpans(depth + 1, spans, child, lim, getJSON);
- });
- return spans;
- },
-
- getJsonSync: function getJsonSync(url) {
- return $.ajax({
- type: "GET",
- url: url,
- async: false,
- dataType: "json"
- }).responseJSON;
- },
-
- appendSVG: function appendSVG(spans) {
- const height_span = 20;
- const width_span = 700;
- const size_tl = 6;
- const margin = {top: 50, bottom: 50, left: 20, right: 1000, process: 300};
-
- var height_screen = spans.length * height_span;
- var dmax = d3.max(spans, function(s) { return s.depth; });
- var tmin = d3.min(spans, function(s) { return s.b; });
- var tmax = d3.max(spans, function(s) { return s.e; });
- var xscale = d3.time.scale()
- .domain([new Date(tmin), new Date(tmax)]).range([0, width_span]);
-
- var svg = d3.select("div[role='main']").append("svg")
- .attr("id", "svg-swimlane")
- .attr("width", width_span + margin.process + margin.left + margin.right)
- .attr("height", height_screen + margin.top + margin.bottom)
- .append("g")
- .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
- var bars = svg.append("g")
- .attr("id", "bars")
- .attr("width", width_span)
- .attr("height", height_screen)
- .attr("transform", "translate(" + (10 * dmax + margin.process) + ", 0)");
-
- var axis = d3.svg.axis()
- .scale(xscale)
- .orient("top")
- .tickValues(xscale.domain())
- .tickFormat(d3.time.format("%x %X.%L"))
- .tickSize(6, 3);
-
- bars.append("g").attr("class", "axis").call(axis);
-
- var span_g = bars.selectAll("g.span")
- .data(spans)
- .enter()
- .append("g")
- .attr("transform", function(s, i) {
- return "translate(0, " + (i * height_span + 5) + ")";
- })
- .classed("timeline", function(d) { return d.t; });
-
- span_g.append("text")
- .text(function(s) { return s.r; })
- .style("alignment-baseline", "hanging")
- .style("font-size", "14px")
- .attr("transform", function(s) {
- return "translate(" + (s.depth * 10 - margin.process - 10 * dmax) + ", 0)";
- });
-
- var rect_g = span_g.append("g")
- .attr("transform", function(s) {
- return "translate(" + xscale(new Date(s.b)) + ", 0)";
- });
-
- rect_g.append("rect")
- .attr("height", height_span - 1)
- .attr("width", function (s) {
- return (width_span * (s.e - s.b)) / (tmax - tmin) + 1;
- })
- .style("fill", "lightblue")
- .attr("class", "span")
-
- rect_g.append("text")
- .text(function(s){ return s.d; })
- .style("alignment-baseline", "hanging")
- .style("font-size", "14px");
-
- rect_g.append("text")
- .text(function(s){ return s.e - s.b; })
- .style("alignment-baseline", "baseline")
- .style("text-anchor", "end")
- .style("font-size", "10px")
- .attr("transform", function(s, i) { return "translate(0, 10)"; });
-
- bars.selectAll("g.timeline").selectAll("rect.timeline")
- .data(function(s) { return s.t; })
- .enter()
- .append("rect")
- .style("fill", "red")
- .attr("class", "timeline")
- .attr("height", size_tl)
- .attr("width", size_tl)
- .attr("transform", function(t) {
- return "translate(" + xscale(t.t) + "," + (height_span - 1 - size_tl) + ")";
- });
-
- var popup = d3.select("div[role='main']").append("div")
- .attr("class", "popup")
- .style("opacity", 0);
-
- bars.selectAll("g.timeline")
- .on("mouseover", function(d) {
- popup.transition().duration(300).style("opacity", .95);
- var text = "<table>";
- d.t.forEach(function (t) {
- text += "<tr><td>" + (t.t - tmin) + "</td>";
- text += "<td> : " + t.m + "</td></tr>";
- });
- text += "</table>"
- popup.html(text)
- .style("left", (document.body.scrollLeft + 50) + "px")
- .style("top", (document.body.scrollTop + 70) + "px")
- .style("width", "700px")
- .style("background", "orange")
- .style("position", "absolute");
- })
- .on("mouseout", function(d) {
- popup.transition().duration(300).style("opacity", 0);
- });
- }
-});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/widget_manager.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/widget_manager.js b/htrace-htraced/src/web/app/widget_manager.js
new file mode 100644
index 0000000..49202c5
--- /dev/null
+++ b/htrace-htraced/src/web/app/widget_manager.js
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Manages a set of widgets on the canvas.
+// Buttons and sliders are both widgets.
+htrace.WidgetManager = function(params) {
+ this.widgets = [];
+ this.focusedWidget = null;
+
+ this.handleMouseDown = function(x, y) {
+ if (this.focusedWidget != null) {
+ this.focusedWidget = null;
+ }
+ var numWidgets = this.widgets.length;
+ console.log("WidgetManager looking through " + numWidgets + " widgets.");
+ for (var i = 0; i < numWidgets; i++) {
+ if (this.widgets[i].handleMouseDown(x, y)) {
+ this.focusedWidget = this.widgets[i];
+ break;
+ }
+ }
+ return (this.focusedWidget != null);
+ };
+
+ this.handleMouseUp = function(x, y) {
+ if (this.focusedWidget != null) {
+ this.focusedWidget.handleMouseUp(x, y);
+ this.focusedWidget = null;
+ }
+ };
+
+ this.handleMouseMove = function(x, y) {
+ return this.focusedWidget != null ?
+ this.focusedWidget.handleMouseMove(x, y) : false;
+ };
+
+ this.draw = function() {
+ var numWidgets = this.widgets.length;
+ for (var i = 0; i < numWidgets; i++) {
+ this.widgets[i].draw();
+ }
+ };
+
+ for (var k in params) {
+ this[k]=params[k];
+ }
+ return this;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/custom.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/custom.css b/htrace-htraced/src/web/custom.css
new file mode 100644
index 0000000..17945cb
--- /dev/null
+++ b/htrace-htraced/src/web/custom.css
@@ -0,0 +1,101 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+.navbar-default {
+ background-color: #001da9;
+ border-color: #b2b5db;
+}
+.navbar-default .navbar-brand {
+ color: #ecf0f1;
+}
+.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus {
+ color: #ffffff;
+}
+.navbar-default .navbar-text {
+ color: #ecf0f1;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #ecf0f1;
+}
+.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus {
+ color: #ffffff;
+}
+.navbar-default .navbar-nav > li > .dropdown-menu {
+ background-color: #001da9;
+}
+.navbar-default .navbar-nav > li > .dropdown-menu > li > a {
+ color: #ecf0f1;
+}
+.navbar-default .navbar-nav > li > .dropdown-menu > li > a:hover,
+.navbar-default .navbar-nav > li > .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ background-color: #b2b5db;
+}
+.navbar-default .navbar-nav > li > .dropdown-menu > li > .divider {
+ background-color: #001da9;
+}
+.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus {
+ color: #ffffff;
+ background-color: #b2b5db;
+}
+.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus {
+ color: #ffffff;
+ background-color: #b2b5db;
+}
+.navbar-default .navbar-toggle {
+ border-color: #b2b5db;
+}
+.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus {
+ background-color: #b2b5db;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #ecf0f1;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #ecf0f1;
+}
+.navbar-default .navbar-link {
+ color: #ecf0f1;
+}
+.navbar-default .navbar-link:hover {
+ color: #ffffff;
+}
+.htrace-canvas-container {
+ overflow: hidden;
+ position: relative;
+}
+.htrace-canvas {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+}
+
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #ecf0f1;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ background-color: #b2b5db;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/index.html
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/index.html b/htrace-htraced/src/web/index.html
index 28abd11..66ef0dc 100644
--- a/htrace-htraced/src/web/index.html
+++ b/htrace-htraced/src/web/index.html
@@ -17,184 +17,208 @@
-->
<html lang="en-US">
<head>
- <meta charset="utf-8">
<title>HTrace</title>
-
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
-
- <!-- TODO: Add Favicon -->
- <link rel="icon" href="//favicon.ico" type="image/x-icon" sizes="16x16">
- <link href="lib/bootstrap-3.3.1/css/bootstrap.css" rel="stylesheet">
- <link href="lib/css/backgrid-0.3.5.min.css" rel="stylesheet">
- <link href="lib/css/backgrid-paginator-0.3.5.min.css" rel="stylesheet">
- <link href="lib/rome-2.1.0/rome.min.css" rel="stylesheet">
- <link href="lib/css/main.css" rel="stylesheet">
-
- <!-- TODO: Remove shiv -->
- <!--[if lt IE 9]>
- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"></script>
- <![endif]-->
+ <meta charset="utf-8" name="viewport"
+ content="width=device-width, initial-scale=1.0">
+ <link href="lib/bootstrap-3.3.1/css/bootstrap.css" rel="stylesheet" type="text/css">
+ <link href="custom.css" rel="stylesheet" type="text/css">
</head>
<body>
<header id="header" role="banner">
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="collapse navbar-collapse">
<a class="navbar-brand" href="#">HTrace</a>
-
<ul class="nav navbar-nav">
- <li class="active"><a href="/">Search</a></li>
+ <li id="about"><a href="#about">About</a></li>
+ <li id="search"><a href="#search">Search</a></li>
</ul>
</div>
</nav>
</header>
-
<div id="app" class="container-fluid" role="application"></div>
-
+ <div id="modal" class="modal fade"></div>
<footer></footer>
- <script id="search-layout-template" type="text/html">
- <div class="container-fluid" id="list" role="application">
+ <script id="about-view-template" type="text/template">
<div class="row">
- <div class="col-md-4" role="form"></div>
- <div class="col-md-8">
- <div class="row">
- <div class="col-md-12" role="main"></div>
- </div>
- <div class="row">
- <div class="col-md-12" role="complementary"></div>
- </div>
+ <div class="col-md-1">
+ </div>
+ <div class="col-md-10">
+ <h1>Welcome to HTrace</h1>
+ <img src="image/owl.png" width="15%">
+ <h2>Server Version</h2>
+ <%= model.get("ReleaseVersion") %>
+ <h2>Server Git Hash</h2>
+ <%= model.get("GitVersion") %>
+ </div>
+ <div class="col-md-1">
</div>
</div>
- </div>
</script>
- <script id="search-controls-template" type="text/html">
- <div class="panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">Controls</h3>
- </div>
- <div class="panel-body">
- <form class="form-horizontal">
- <div class="search-fields"></div>
- <div class="form-group">
- <div class="col-sm-12">
- <div class="btn-group">
- <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- Add Field <span class="caret"></span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a href="javascript:void(0)" class="add-field" data-field="begin">Start Date/Time</a></li>
- <li><a href="javascript:void(0)" class="add-field" data-field="end">End Date/Time</a></li>
- <li><a href="javascript:void(0)" class="add-field" data-field="duration">Duration</a></li>
- </ul>
+ <script id="search-view-template" type="text/template">
+ <div class="row" id="searchView">
+ <div class="col-md-3" role="form">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h1 class="panel-title">Search</h1>
+ </div style="border: 1px solid #000000;">
+ <div class="panel-body">
+ <form>
+ <div id="predicates">
+ </div>
+ <div class="form-group">
+ <div class="btn-group">
+ <button type="button" data-toggle="dropdown"
+ aria-expanded="false"
+ class="btn btn-default dropdown-toggle">
+ Add Predicate<span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="javascript:void(0)"
+ class="add-field">Began after</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Began at or before</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Ended after</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Ended at or before</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Description contains</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Description is exactly</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Duration is longer than</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Duration is at most</a></li>
+ <li><a href="javascript:void(0)"
+ class="add-field">Span ID is</a></li>
+ </ul>
+ </div>
+ <button type="submit" class="btn btn-primary" id="searchButton">
+ Search</button>
+ </div>
+ <div class="form-group">
+ <button type="button" class="btn btn btn-danger" id="clearButton">
+ Clear</button>
+ </div>
+ </form>
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h1 class="panel-title">Timeline</h1>
+ </div style="border: 1px solid #000000;">
+ <div class="panel-body">
+ <div class="form-horizontal">
+ <div class="form-group">
+ <label class="col-sm-2 control-label">Begin</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" id="begin" value="1970-01-01T00:00:00,000"/>
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-2 control-label">End</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" id="end" value="1970-01-01T00:00:00,100"/>
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-2 control-label">Cur</label>
+ <div class="col-sm-10">
+ <input type="text" class="form-control" id="selectedTime" value=""/>
+ </div>
+ </div>
+ <div class="form-horizontal">
+ <button type="button" class="btn btn btn-warning"
+ id="zoomButton">Zoom</button>
+ </div>
</div>
</div>
</div>
- <div class="form-group">
- <div class="col-sm-12">
- <button type="button" class="search btn btn-default">Search</button>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h1 class="panel-title">Span Details</h1>
+ </div style="border: 1px solid #000000;">
+ <div class="panel-body">
+ <div id="spanDetails" ></div>
</div>
</div>
- </form>
- </div>
- </div>
- </script>
-
- <script id='search-field-template' type='text/html'>
- <div class='form-group search-field start-end-date-time'>
- <label for="start-end-date-time" class="start-end-date-time control-label col-sm-3">Date</label>
- <div class="col-sm-3">
- <select class='op form-control'>
- <option selected value='ge'>After</option>
- <option value='le'>Before</option>
- </select>
- </div>
- <div class='col-sm-5'>
- <input placeholder="Date/Time" id="start-end-date-time" class="start-end-date-time date form-control value" />
- </div>
- <button class="btn btn-link remove-field" type="button">x</button>
- </div>
- <div class='form-group search-field duration'>
- <label for="duration" class="duration control-label col-sm-3">Duration</label>
- <div class='col-sm-8'>
- <input type="text" class="duration form-control value" placeholder="Duration" />
</div>
- <button class="btn btn-link remove-field" type="button">x</button>
- </div>
- <div class='form-group search-field description'>
- <label for="description" class="description control-label col-sm-3">Description</label>
- <div class='col-sm-8'>
- <input type="search" id="description" class="description value form-control" placeholder="Search description" />
+ <div class="col-md-9" id="resultsView">
+ <div id="results">
+ <h3>...</h3>
+ </div>
</div>
</div>
</script>
- <script id="details-layout-template" type="text/html">
- <div class="container-fluid" id="list" role="application">
- <div class="row">
- <div class="col-md-12" role="main"></div>
- </div>
-
- <hr>
-
- <div class="row">
- <div class="col-md-12" role="complementary"></div>
- </div>
- </div>
+ <script id="predicate-template" type="text/template">
+ <form class="form-horizontal">
+ <div class="form-group">
+ <%= desc %>
+ <button type="button" class="btn pull-right btn-link btn-sm closeButton"
+ >X</button><br/>
+ <input type="text" class="form-control"/>
+ </div>
+ </form>
</script>
- <script id="span-details-template" type="text/html">
- <table class="table table-condensed">
- <thead>
- <tr>
- <th>Description</th>
- <th>Span ID</th>
- <th>Process ID</th>
- <th>Start time</th>
- <th>End time</th>
- <th>Duration</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><%- span.description %></td>
- <td><%- span.spanId %></td>
- <td><%- span.processId %></td>
- <td><%- span.beginTime %></td>
- <td><%- span.stopTime %></td>
- <td><%- span.duration %></td>
- </tr>
- </tbody>
- </table>
+ <script id="search-results-view-template" type="text/template">
+ <div id="resultsDiv" class="htrace-canvas-container">
+ <canvas id="resultsCanvas" class="htrace-canvas">
+ <h2>Sorry, your browser does not support the HTML5 canvas element. Please
+ upgrade to a newer browser.</h2>
+ </canvas>
+ </div>
</script>
- <script id="swimlane-layout-template" type="text/html">
- <div class="container-fluid" id="list" role="application">
- <div class="row">
- <div class="col-md-12" role="main"></div>
+ <script id="modal-warning-template" type="text/template">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal"
+ aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title"><%= title %></h4>
+ </div>
+ <div class="modal-body">
+ <%= body %><p/>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
+ </div>
+ </div>
</div>
- </div>
</script>
- <script src="lib/js/jquery-2.1.3.min.js" type="text/javascript"></script>
- <script src="lib/js/d3-3.5.5.js" type="text/javascript"></script>
+ <script src="lib/jquery-2.1.4.js" type="text/javascript"></script>
<script src="lib/bootstrap-3.3.1/js/bootstrap.min.js" type="text/javascript"></script>
- <script src="lib/js/underscore-1.7.0.js" type="text/javascript"></script>
- <script src="lib/js/backbone-1.1.2.js" type="text/javascript"></script>
- <script src="lib/js/backbone.marionette-2.4.1.min.js" type="text/javascript"></script>
- <script src="lib/js/backbone.paginator-2.0.2.js" type="text/javascript"></script>
- <script src="lib/js/backgrid-0.3.5.js" type="text/javascript"></script>
- <script src="lib/js/backgrid-paginator-0.3.5.js" type="text/javascript"></script>
- <script src="lib/js/moment-2.9.0.min.js" type="text/javascript"></script>
- <script src="lib/rome-2.1.0/rome.standalone.min.js" type="text/javascript"></script>
-
- <script src="app/app.js" type="text/javascript"></script>
- <script src="app/models/span.js" type="text/javascript"></script>
- <script src="app/views/graph/graph.js" type="text/javascript"></script>
- <script src="app/views/search/field.js" type="text/javascript"></script>
- <script src="app/views/search/search.js" type="text/javascript"></script>
- <script src="app/views/details/details.js" type="text/javascript"></script>
- <script src="app/views/swimlane/swimlane.js" type="text/javascript"></script>
- <script src="app/setup.js" type="text/javascript"></script>
+ <script src="lib/underscore-1.7.0.js" type="text/javascript"></script>
+ <script src="lib/backbone-1.1.2.js" type="text/javascript"></script>
+ <script src="lib/moment-2.10.3.js" type="text/javascript"></script>
+
+ <script src="app/string.js" type="text/javascript"></script>
+ <script src="app/time_cursor.js" type="text/javascript"></script>
+
+ <script src="app/widget_manager.js" type="text/javascript"></script>
+ <script src="app/triangle_button.js" type="text/javascript"></script>
+
+ <script src="app/span.js" type="text/javascript"></script>
+
+ <script src="app/span_widget.js" type="text/javascript"></script>
+ <script src="app/search_results.js" type="text/javascript"></script>
+ <script src="app/about_view.js" type="text/javascript"></script>
+ <script src="app/modal.js" type="text/javascript"></script>
+ <script src="app/predicate.js" type="text/javascript"></script>
+ <script src="app/predicate_view.js" type="text/javascript"></script>
+ <script src="app/query_results.js" type="text/javascript"></script>
+ <script src="app/search_results_view.js" type="text/javascript"></script>
+ <script src="app/search_view.js" type="text/javascript"></script>
+ <script src="app/server_info.js" type="text/javascript"></script>
+
+ <script src="app/router.js" type="text/javascript"></script>
</body>
</html>
+
[12/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/backbone.paginator-2.0.2.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/backbone.paginator-2.0.2.js b/htrace-htraced/src/web/lib/js/backbone.paginator-2.0.2.js
deleted file mode 100644
index d8ccc65..0000000
--- a/htrace-htraced/src/web/lib/js/backbone.paginator-2.0.2.js
+++ /dev/null
@@ -1,1325 +0,0 @@
-/*
- backbone.paginator 2.0.0
- http://github.com/backbone-paginator/backbone.paginator
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT @license.
-*/
-
-(function (factory) {
-
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(require("underscore"), require("backbone"));
- }
- // AMD
- else if (typeof define == "function" && define.amd) {
- define(["underscore", "backbone"], factory);
- }
- // Browser
- else if (typeof _ !== "undefined" && typeof Backbone !== "undefined") {
- var oldPageableCollection = Backbone.PageableCollection;
- var PageableCollection = factory(_, Backbone);
-
- /**
- __BROWSER ONLY__
-
- If you already have an object named `PageableCollection` attached to the
- `Backbone` module, you can use this to return a local reference to this
- Backbone.PageableCollection class and reset the name
- Backbone.PageableCollection to its previous definition.
-
- // The left hand side gives you a reference to this
- // Backbone.PageableCollection implementation, the right hand side
- // resets Backbone.PageableCollection to your other
- // Backbone.PageableCollection.
- var PageableCollection = Backbone.PageableCollection.noConflict();
-
- @static
- @member Backbone.PageableCollection
- @return {Backbone.PageableCollection}
- */
- Backbone.PageableCollection.noConflict = function () {
- Backbone.PageableCollection = oldPageableCollection;
- return PageableCollection;
- };
- }
-
-}(function (_, Backbone) {
-
- "use strict";
-
- var _extend = _.extend;
- var _omit = _.omit;
- var _clone = _.clone;
- var _each = _.each;
- var _pick = _.pick;
- var _contains = _.contains;
- var _isEmpty = _.isEmpty;
- var _pairs = _.pairs;
- var _invert = _.invert;
- var _isArray = _.isArray;
- var _isFunction = _.isFunction;
- var _isObject = _.isObject;
- var _keys = _.keys;
- var _isUndefined = _.isUndefined;
- var ceil = Math.ceil;
- var floor = Math.floor;
- var max = Math.max;
-
- var BBColProto = Backbone.Collection.prototype;
-
- function finiteInt (val, name) {
- if (!_.isNumber(val) || _.isNaN(val) || !_.isFinite(val) || ~~val !== val) {
- throw new TypeError("`" + name + "` must be a finite integer");
- }
- return val;
- }
-
- function queryStringToParams (qs) {
- var kvp, k, v, ls, params = {}, decode = decodeURIComponent;
- var kvps = qs.split('&');
- for (var i = 0, l = kvps.length; i < l; i++) {
- var param = kvps[i];
- kvp = param.split('='), k = kvp[0], v = kvp[1] || true;
- k = decode(k), v = decode(v), ls = params[k];
- if (_isArray(ls)) ls.push(v);
- else if (ls) params[k] = [ls, v];
- else params[k] = v;
- }
- return params;
- }
-
- // hack to make sure the whatever event handlers for this event is run
- // before func is, and the event handlers that func will trigger.
- function runOnceAtLastHandler (col, event, func) {
- var eventHandlers = col._events[event];
- if (eventHandlers && eventHandlers.length) {
- var lastHandler = eventHandlers[eventHandlers.length - 1];
- var oldCallback = lastHandler.callback;
- lastHandler.callback = function () {
- try {
- oldCallback.apply(this, arguments);
- func();
- }
- catch (e) {
- throw e;
- }
- finally {
- lastHandler.callback = oldCallback;
- }
- };
- }
- else func();
- }
-
- var PARAM_TRIM_RE = /[\s'"]/g;
- var URL_TRIM_RE = /[<>\s'"]/g;
-
- /**
- Drop-in replacement for Backbone.Collection. Supports server-side and
- client-side pagination and sorting. Client-side mode also support fully
- multi-directional synchronization of changes between pages.
-
- @class Backbone.PageableCollection
- @extends Backbone.Collection
- */
- var PageableCollection = Backbone.PageableCollection = Backbone.Collection.extend({
-
- /**
- The container object to store all pagination states.
-
- You can override the default state by extending this class or specifying
- them in an `options` hash to the constructor.
-
- @property {Object} state
-
- @property {0|1} [state.firstPage=1] The first page index. Set to 0 if
- your server API uses 0-based indices. You should only override this value
- during extension, initialization or reset by the server after
- fetching. This value should be read only at other times.
-
- @property {number} [state.lastPage=null] The last page index. This value
- is __read only__ and it's calculated based on whether `firstPage` is 0 or
- 1, during bootstrapping, fetching and resetting. Please don't change this
- value under any circumstances.
-
- @property {number} [state.currentPage=null] The current page index. You
- should only override this value during extension, initialization or reset
- by the server after fetching. This value should be read only at other
- times. Can be a 0-based or 1-based index, depending on whether
- `firstPage` is 0 or 1. If left as default, it will be set to `firstPage`
- on initialization.
-
- @property {number} [state.pageSize=25] How many records to show per
- page. This value is __read only__ after initialization, if you want to
- change the page size after initialization, you must call #setPageSize.
-
- @property {number} [state.totalPages=null] How many pages there are. This
- value is __read only__ and it is calculated from `totalRecords`.
-
- @property {number} [state.totalRecords=null] How many records there
- are. This value is __required__ under server mode. This value is optional
- for client mode as the number will be the same as the number of models
- during bootstrapping and during fetching, either supplied by the server
- in the metadata, or calculated from the size of the response.
-
- @property {string} [state.sortKey=null] The model attribute to use for
- sorting.
-
- @property {-1|0|1} [state.order=-1] The order to use for sorting. Specify
- -1 for ascending order or 1 for descending order. If 0, no client side
- sorting will be done and the order query parameter will not be sent to
- the server during a fetch.
- */
- state: {
- firstPage: 1,
- lastPage: null,
- currentPage: null,
- pageSize: 25,
- totalPages: null,
- totalRecords: null,
- sortKey: null,
- order: -1
- },
-
- /**
- @property {"server"|"client"|"infinite"} [mode="server"] The mode of
- operations for this collection. `"server"` paginates on the server-side,
- `"client"` paginates on the client-side and `"infinite"` paginates on the
- server-side for APIs that do not support `totalRecords`.
- */
- mode: "server",
-
- /**
- A translation map to convert Backbone.PageableCollection state attributes
- to the query parameters accepted by your server API.
-
- You can override the default state by extending this class or specifying
- them in `options.queryParams` object hash to the constructor.
-
- @property {Object} queryParams
- @property {string} [queryParams.currentPage="page"]
- @property {string} [queryParams.pageSize="per_page"]
- @property {string} [queryParams.totalPages="total_pages"]
- @property {string} [queryParams.totalRecords="total_entries"]
- @property {string} [queryParams.sortKey="sort_by"]
- @property {string} [queryParams.order="order"]
- @property {string} [queryParams.directions={"-1": "asc", "1": "desc"}] A
- map for translating a Backbone.PageableCollection#state.order constant to
- the ones your server API accepts.
- */
- queryParams: {
- currentPage: "page",
- pageSize: "per_page",
- totalPages: "total_pages",
- totalRecords: "total_entries",
- sortKey: "sort_by",
- order: "order",
- directions: {
- "-1": "asc",
- "1": "desc"
- }
- },
-
- /**
- __CLIENT MODE ONLY__
-
- This collection is the internal storage for the bootstrapped or fetched
- models. You can use this if you want to operate on all the pages.
-
- @property {Backbone.Collection} fullCollection
- */
-
- /**
- Given a list of models or model attributues, bootstraps the full
- collection in client mode or infinite mode, or just the page you want in
- server mode.
-
- If you want to initialize a collection to a different state than the
- default, you can specify them in `options.state`. Any state parameters
- supplied will be merged with the default. If you want to change the
- default mapping from #state keys to your server API's query parameter
- names, you can specifiy an object hash in `option.queryParams`. Likewise,
- any mapping provided will be merged with the default. Lastly, all
- Backbone.Collection constructor options are also accepted.
-
- See:
-
- - Backbone.PageableCollection#state
- - Backbone.PageableCollection#queryParams
- - [Backbone.Collection#initialize](http://backbonejs.org/#Collection-constructor)
-
- @param {Array.<Object>} [models]
-
- @param {Object} [options]
-
- @param {function(*, *): number} [options.comparator] If specified, this
- comparator is set to the current page under server mode, or the #fullCollection
- otherwise.
-
- @param {boolean} [options.full] If `false` and either a
- `options.comparator` or `sortKey` is defined, the comparator is attached
- to the current page. Default is `true` under client or infinite mode and
- the comparator will be attached to the #fullCollection.
-
- @param {Object} [options.state] The state attributes overriding the defaults.
-
- @param {string} [options.state.sortKey] The model attribute to use for
- sorting. If specified instead of `options.comparator`, a comparator will
- be automatically created using this value, and optionally a sorting order
- specified in `options.state.order`. The comparator is then attached to
- the new collection instance.
-
- @param {-1|1} [options.state.order] The order to use for sorting. Specify
- -1 for ascending order and 1 for descending order.
-
- @param {Object} [options.queryParam]
- */
- constructor: function (models, options) {
-
- BBColProto.constructor.apply(this, arguments);
-
- options = options || {};
-
- var mode = this.mode = options.mode || this.mode || PageableProto.mode;
-
- var queryParams = _extend({}, PageableProto.queryParams, this.queryParams,
- options.queryParams || {});
-
- queryParams.directions = _extend({},
- PageableProto.queryParams.directions,
- this.queryParams.directions,
- queryParams.directions || {});
-
- this.queryParams = queryParams;
-
- var state = this.state = _extend({}, PageableProto.state, this.state,
- options.state || {});
-
- state.currentPage = state.currentPage == null ?
- state.firstPage :
- state.currentPage;
-
- if (!_isArray(models)) models = models ? [models] : [];
- models = models.slice();
-
- if (mode != "server" && state.totalRecords == null && !_isEmpty(models)) {
- state.totalRecords = models.length;
- }
-
- this.switchMode(mode, _extend({fetch: false,
- resetState: false,
- models: models}, options));
-
- var comparator = options.comparator;
-
- if (state.sortKey && !comparator) {
- this.setSorting(state.sortKey, state.order, options);
- }
-
- if (mode != "server") {
- var fullCollection = this.fullCollection;
-
- if (comparator && options.full) {
- this.comparator = null;
- fullCollection.comparator = comparator;
- }
-
- if (options.full) fullCollection.sort();
-
- // make sure the models in the current page and full collection have the
- // same references
- if (models && !_isEmpty(models)) {
- this.reset(models, _extend({silent: true}, options));
- this.getPage(state.currentPage);
- models.splice.apply(models, [0, models.length].concat(this.models));
- }
- }
-
- this._initState = _clone(this.state);
- },
-
- /**
- Makes a Backbone.Collection that contains all the pages.
-
- @private
- @param {Array.<Object|Backbone.Model>} models
- @param {Object} options Options for Backbone.Collection constructor.
- @return {Backbone.Collection}
- */
- _makeFullCollection: function (models, options) {
-
- var properties = ["url", "model", "sync", "comparator"];
- var thisProto = this.constructor.prototype;
- var i, length, prop;
-
- var proto = {};
- for (i = 0, length = properties.length; i < length; i++) {
- prop = properties[i];
- if (!_isUndefined(thisProto[prop])) {
- proto[prop] = thisProto[prop];
- }
- }
-
- var fullCollection = new (Backbone.Collection.extend(proto))(models, options);
-
- for (i = 0, length = properties.length; i < length; i++) {
- prop = properties[i];
- if (this[prop] !== thisProto[prop]) {
- fullCollection[prop] = this[prop];
- }
- }
-
- return fullCollection;
- },
-
- /**
- Factory method that returns a Backbone event handler that responses to
- the `add`, `remove`, `reset`, and the `sort` events. The returned event
- handler will synchronize the current page collection and the full
- collection's models.
-
- @private
-
- @param {Backbone.PageableCollection} pageCol
- @param {Backbone.Collection} fullCol
-
- @return {function(string, Backbone.Model, Backbone.Collection, Object)}
- Collection event handler
- */
- _makeCollectionEventHandler: function (pageCol, fullCol) {
-
- return function collectionEventHandler (event, model, collection, options) {
-
- var handlers = pageCol._handlers;
- _each(_keys(handlers), function (event) {
- var handler = handlers[event];
- pageCol.off(event, handler);
- fullCol.off(event, handler);
- });
-
- var state = _clone(pageCol.state);
- var firstPage = state.firstPage;
- var currentPage = firstPage === 0 ?
- state.currentPage :
- state.currentPage - 1;
- var pageSize = state.pageSize;
- var pageStart = currentPage * pageSize, pageEnd = pageStart + pageSize;
-
- if (event == "add") {
- var pageIndex, fullIndex, addAt, colToAdd, options = options || {};
- if (collection == fullCol) {
- fullIndex = fullCol.indexOf(model);
- if (fullIndex >= pageStart && fullIndex < pageEnd) {
- colToAdd = pageCol;
- pageIndex = addAt = fullIndex - pageStart;
- }
- }
- else {
- pageIndex = pageCol.indexOf(model);
- fullIndex = pageStart + pageIndex;
- colToAdd = fullCol;
- var addAt = !_isUndefined(options.at) ?
- options.at + pageStart :
- fullIndex;
- }
-
- if (!options.onRemove) {
- ++state.totalRecords;
- delete options.onRemove;
- }
-
- pageCol.state = pageCol._checkState(state);
-
- if (colToAdd) {
- colToAdd.add(model, _extend({}, options || {}, {at: addAt}));
- var modelToRemove = pageIndex >= pageSize ?
- model :
- !_isUndefined(options.at) && addAt < pageEnd && pageCol.length > pageSize ?
- pageCol.at(pageSize) :
- null;
- if (modelToRemove) {
- runOnceAtLastHandler(collection, event, function () {
- pageCol.remove(modelToRemove, {onAdd: true});
- });
- }
- }
- }
-
- // remove the model from the other collection as well
- if (event == "remove") {
- if (!options.onAdd) {
- // decrement totalRecords and update totalPages and lastPage
- if (!--state.totalRecords) {
- state.totalRecords = null;
- state.totalPages = null;
- }
- else {
- var totalPages = state.totalPages = ceil(state.totalRecords / pageSize);
- state.lastPage = firstPage === 0 ? totalPages - 1 : totalPages || firstPage;
- if (state.currentPage > totalPages) state.currentPage = state.lastPage;
- }
- pageCol.state = pageCol._checkState(state);
-
- var nextModel, removedIndex = options.index;
- if (collection == pageCol) {
- if (nextModel = fullCol.at(pageEnd)) {
- runOnceAtLastHandler(pageCol, event, function () {
- pageCol.push(nextModel, {onRemove: true});
- });
- }
- else if (!pageCol.length && state.totalRecords) {
- pageCol.reset(fullCol.models.slice(pageStart - pageSize, pageEnd - pageSize),
- _extend({}, options, {parse: false}));
- }
- fullCol.remove(model);
- }
- else if (removedIndex >= pageStart && removedIndex < pageEnd) {
- if (nextModel = fullCol.at(pageEnd - 1)) {
- runOnceAtLastHandler(pageCol, event, function() {
- pageCol.push(nextModel, {onRemove: true});
- });
- }
- pageCol.remove(model);
- if (!pageCol.length && state.totalRecords) {
- pageCol.reset(fullCol.models.slice(pageStart - pageSize, pageEnd - pageSize),
- _extend({}, options, {parse: false}));
- }
- }
- }
- else delete options.onAdd;
- }
-
- if (event == "reset") {
- options = collection;
- collection = model;
-
- // Reset that's not a result of getPage
- if (collection == pageCol && options.from == null &&
- options.to == null) {
- var head = fullCol.models.slice(0, pageStart);
- var tail = fullCol.models.slice(pageStart + pageCol.models.length);
- fullCol.reset(head.concat(pageCol.models).concat(tail), options);
- }
- else if (collection == fullCol) {
- if (!(state.totalRecords = fullCol.models.length)) {
- state.totalRecords = null;
- state.totalPages = null;
- }
- if (pageCol.mode == "client") {
- state.lastPage = state.currentPage = state.firstPage;
- }
- pageCol.state = pageCol._checkState(state);
- pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
- _extend({}, options, {parse: false}));
- }
- }
-
- if (event == "sort") {
- options = collection;
- collection = model;
- if (collection === fullCol) {
- pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
- _extend({}, options, {parse: false}));
- }
- }
-
- _each(_keys(handlers), function (event) {
- var handler = handlers[event];
- _each([pageCol, fullCol], function (col) {
- col.on(event, handler);
- var callbacks = col._events[event] || [];
- callbacks.unshift(callbacks.pop());
- });
- });
- };
- },
-
- /**
- Sanity check this collection's pagination states. Only perform checks
- when all the required pagination state values are defined and not null.
- If `totalPages` is undefined or null, it is set to `totalRecords` /
- `pageSize`. `lastPage` is set according to whether `firstPage` is 0 or 1
- when no error occurs.
-
- @private
-
- @throws {TypeError} If `totalRecords`, `pageSize`, `currentPage` or
- `firstPage` is not a finite integer.
-
- @throws {RangeError} If `pageSize`, `currentPage` or `firstPage` is out
- of bounds.
-
- @return {Object} Returns the `state` object if no error was found.
- */
- _checkState: function (state) {
-
- var mode = this.mode;
- var links = this.links;
- var totalRecords = state.totalRecords;
- var pageSize = state.pageSize;
- var currentPage = state.currentPage;
- var firstPage = state.firstPage;
- var totalPages = state.totalPages;
-
- if (totalRecords != null && pageSize != null && currentPage != null &&
- firstPage != null && (mode == "infinite" ? links : true)) {
-
- totalRecords = finiteInt(totalRecords, "totalRecords");
- pageSize = finiteInt(pageSize, "pageSize");
- currentPage = finiteInt(currentPage, "currentPage");
- firstPage = finiteInt(firstPage, "firstPage");
-
- if (pageSize < 1) {
- throw new RangeError("`pageSize` must be >= 1");
- }
-
- totalPages = state.totalPages = ceil(totalRecords / pageSize);
-
- if (firstPage < 0 || firstPage > 1) {
- throw new RangeError("`firstPage must be 0 or 1`");
- }
-
- state.lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages || firstPage;
-
- if (mode == "infinite") {
- if (!links[currentPage + '']) {
- throw new RangeError("No link found for page " + currentPage);
- }
- }
- else if (currentPage < firstPage ||
- (totalPages > 0 &&
- (firstPage ? currentPage > totalPages : currentPage >= totalPages))) {
- throw new RangeError("`currentPage` must be firstPage <= currentPage " +
- (firstPage ? ">" : ">=") +
- " totalPages if " + firstPage + "-based. Got " +
- currentPage + '.');
- }
- }
-
- return state;
- },
-
- /**
- Change the page size of this collection.
-
- Under most if not all circumstances, you should call this method to
- change the page size of a pageable collection because it will keep the
- pagination state sane. By default, the method will recalculate the
- current page number to one that will retain the current page's models
- when increasing the page size. When decreasing the page size, this method
- will retain the last models to the current page that will fit into the
- smaller page size.
-
- If `options.first` is true, changing the page size will also reset the
- current page back to the first page instead of trying to be smart.
-
- For server mode operations, changing the page size will trigger a #fetch
- and subsequently a `reset` event.
-
- For client mode operations, changing the page size will `reset` the
- current page by recalculating the current page boundary on the client
- side.
-
- If `options.fetch` is true, a fetch can be forced if the collection is in
- client mode.
-
- @param {number} pageSize The new page size to set to #state.
- @param {Object} [options] {@link #fetch} options.
- @param {boolean} [options.first=false] Reset the current page number to
- the first page if `true`.
- @param {boolean} [options.fetch] If `true`, force a fetch in client mode.
-
- @throws {TypeError} If `pageSize` is not a finite integer.
- @throws {RangeError} If `pageSize` is less than 1.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- setPageSize: function (pageSize, options) {
- pageSize = finiteInt(pageSize, "pageSize");
-
- options = options || {first: false};
-
- var state = this.state;
- var totalPages = ceil(state.totalRecords / pageSize);
- var currentPage = totalPages ?
- max(state.firstPage, floor(totalPages * state.currentPage / state.totalPages)) :
- state.firstPage;
-
- state = this.state = this._checkState(_extend({}, state, {
- pageSize: pageSize,
- currentPage: options.first ? state.firstPage : currentPage,
- totalPages: totalPages
- }));
-
- return this.getPage(state.currentPage, _omit(options, ["first"]));
- },
-
- /**
- Switching between client, server and infinite mode.
-
- If switching from client to server mode, the #fullCollection is emptied
- first and then deleted and a fetch is immediately issued for the current
- page from the server. Pass `false` to `options.fetch` to skip fetching.
-
- If switching to infinite mode, and if `options.models` is given for an
- array of models, #links will be populated with a URL per page, using the
- default URL for this collection.
-
- If switching from server to client mode, all of the pages are immediately
- refetched. If you have too many pages, you can pass `false` to
- `options.fetch` to skip fetching.
-
- If switching to any mode from infinite mode, the #links will be deleted.
-
- @param {"server"|"client"|"infinite"} [mode] The mode to switch to.
-
- @param {Object} [options]
-
- @param {boolean} [options.fetch=true] If `false`, no fetching is done.
-
- @param {boolean} [options.resetState=true] If 'false', the state is not
- reset, but checked for sanity instead.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this if `options.fetch` is `false`.
- */
- switchMode: function (mode, options) {
-
- if (!_contains(["server", "client", "infinite"], mode)) {
- throw new TypeError('`mode` must be one of "server", "client" or "infinite"');
- }
-
- options = options || {fetch: true, resetState: true};
-
- var state = this.state = options.resetState ?
- _clone(this._initState) :
- this._checkState(_extend({}, this.state));
-
- this.mode = mode;
-
- var self = this;
- var fullCollection = this.fullCollection;
- var handlers = this._handlers = this._handlers || {}, handler;
- if (mode != "server" && !fullCollection) {
- fullCollection = this._makeFullCollection(options.models || [], options);
- fullCollection.pageableCollection = this;
- this.fullCollection = fullCollection;
- var allHandler = this._makeCollectionEventHandler(this, fullCollection);
- _each(["add", "remove", "reset", "sort"], function (event) {
- handlers[event] = handler = _.bind(allHandler, {}, event);
- self.on(event, handler);
- fullCollection.on(event, handler);
- });
- fullCollection.comparator = this._fullComparator;
- }
- else if (mode == "server" && fullCollection) {
- _each(_keys(handlers), function (event) {
- handler = handlers[event];
- self.off(event, handler);
- fullCollection.off(event, handler);
- });
- delete this._handlers;
- this._fullComparator = fullCollection.comparator;
- delete this.fullCollection;
- }
-
- if (mode == "infinite") {
- var links = this.links = {};
- var firstPage = state.firstPage;
- var totalPages = ceil(state.totalRecords / state.pageSize);
- var lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages || firstPage;
- for (var i = state.firstPage; i <= lastPage; i++) {
- links[i] = this.url;
- }
- }
- else if (this.links) delete this.links;
-
- return options.fetch ?
- this.fetch(_omit(options, "fetch", "resetState")) :
- this;
- },
-
- /**
- @return {boolean} `true` if this collection can page backward, `false`
- otherwise.
- */
- hasPreviousPage: function () {
- var state = this.state;
- var currentPage = state.currentPage;
- if (this.mode != "infinite") return currentPage > state.firstPage;
- return !!this.links[currentPage - 1];
- },
-
- /**
- @return {boolean} `true` if this collection can page forward, `false`
- otherwise.
- */
- hasNextPage: function () {
- var state = this.state;
- var currentPage = this.state.currentPage;
- if (this.mode != "infinite") return currentPage < state.lastPage;
- return !!this.links[currentPage + 1];
- },
-
- /**
- Fetch the first page in server mode, or reset the current page of this
- collection to the first page in client or infinite mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getFirstPage: function (options) {
- return this.getPage("first", options);
- },
-
- /**
- Fetch the previous page in server mode, or reset the current page of this
- collection to the previous page in client or infinite mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPreviousPage: function (options) {
- return this.getPage("prev", options);
- },
-
- /**
- Fetch the next page in server mode, or reset the current page of this
- collection to the next page in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getNextPage: function (options) {
- return this.getPage("next", options);
- },
-
- /**
- Fetch the last page in server mode, or reset the current page of this
- collection to the last page in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getLastPage: function (options) {
- return this.getPage("last", options);
- },
-
- /**
- Given a page index, set #state.currentPage to that index. If this
- collection is in server mode, fetch the page using the updated state,
- otherwise, reset the current page of this collection to the page
- specified by `index` in client mode. If `options.fetch` is true, a fetch
- can be forced in client mode before resetting the current page. Under
- infinite mode, if the index is less than the current page, a reset is
- done as in client mode. If the index is greater than the current page
- number, a fetch is made with the results **appended** to #fullCollection.
- The current page will then be reset after fetching.
-
- @param {number|string} index The page index to go to, or the page name to
- look up from #links in infinite mode.
- @param {Object} [options] {@link #fetch} options or
- [reset](http://backbonejs.org/#Collection-reset) options for client mode
- when `options.fetch` is `false`.
- @param {boolean} [options.fetch=false] If true, force a {@link #fetch} in
- client mode.
-
- @throws {TypeError} If `index` is not a finite integer under server or
- client mode, or does not yield a URL from #links under infinite mode.
-
- @throws {RangeError} If `index` is out of bounds.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPage: function (index, options) {
-
- var mode = this.mode, fullCollection = this.fullCollection;
-
- options = options || {fetch: false};
-
- var state = this.state,
- firstPage = state.firstPage,
- currentPage = state.currentPage,
- lastPage = state.lastPage,
- pageSize = state.pageSize;
-
- var pageNum = index;
- switch (index) {
- case "first": pageNum = firstPage; break;
- case "prev": pageNum = currentPage - 1; break;
- case "next": pageNum = currentPage + 1; break;
- case "last": pageNum = lastPage; break;
- default: pageNum = finiteInt(index, "index");
- }
-
- this.state = this._checkState(_extend({}, state, {currentPage: pageNum}));
-
- options.from = currentPage, options.to = pageNum;
-
- var pageStart = (firstPage === 0 ? pageNum : pageNum - 1) * pageSize;
- var pageModels = fullCollection && fullCollection.length ?
- fullCollection.models.slice(pageStart, pageStart + pageSize) :
- [];
- if ((mode == "client" || (mode == "infinite" && !_isEmpty(pageModels))) &&
- !options.fetch) {
- this.reset(pageModels, _omit(options, "fetch"));
- return this;
- }
-
- if (mode == "infinite") options.url = this.links[pageNum];
-
- return this.fetch(_omit(options, "fetch"));
- },
-
- /**
- Fetch the page for the provided item offset in server mode, or reset the current page of this
- collection to the page for the provided item offset in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPageByOffset: function (offset, options) {
- if (offset < 0) {
- throw new RangeError("`offset must be > 0`");
- }
- offset = finiteInt(offset);
-
- var page = floor(offset / this.state.pageSize);
- if (this.state.firstPage !== 0) page++;
- if (page > this.state.lastPage) page = this.state.lastPage;
- return this.getPage(page, options);
- },
-
- /**
- Overidden to make `getPage` compatible with Zepto.
-
- @param {string} method
- @param {Backbone.Model|Backbone.Collection} model
- @param {Object} [options]
-
- @return {XMLHttpRequest}
- */
- sync: function (method, model, options) {
- var self = this;
- if (self.mode == "infinite") {
- var success = options.success;
- var currentPage = self.state.currentPage;
- options.success = function (resp, status, xhr) {
- var links = self.links;
- var newLinks = self.parseLinks(resp, _extend({xhr: xhr}, options));
- if (newLinks.first) links[self.state.firstPage] = newLinks.first;
- if (newLinks.prev) links[currentPage - 1] = newLinks.prev;
- if (newLinks.next) links[currentPage + 1] = newLinks.next;
- if (success) success(resp, status, xhr);
- };
- }
-
- return (BBColProto.sync || Backbone.sync).call(self, method, model, options);
- },
-
- /**
- Parse pagination links from the server response. Only valid under
- infinite mode.
-
- Given a response body and a XMLHttpRequest object, extract pagination
- links from them for infinite paging.
-
- This default implementation parses the RFC 5988 `Link` header and extract
- 3 links from it - `first`, `prev`, `next`. Any subclasses overriding this
- method __must__ return an object hash having only the keys
- above. However, simply returning a `next` link or an empty hash if there
- are no more links should be enough for most implementations.
-
- @param {*} resp The deserialized response body.
- @param {Object} [options]
- @param {XMLHttpRequest} [options.xhr] The XMLHttpRequest object for this
- response.
- @return {Object}
- */
- parseLinks: function (resp, options) {
- var links = {};
- var linkHeader = options.xhr.getResponseHeader("Link");
- if (linkHeader) {
- var relations = ["first", "prev", "next"];
- _each(linkHeader.split(","), function (linkValue) {
- var linkParts = linkValue.split(";");
- var url = linkParts[0].replace(URL_TRIM_RE, '');
- var params = linkParts.slice(1);
- _each(params, function (param) {
- var paramParts = param.split("=");
- var key = paramParts[0].replace(PARAM_TRIM_RE, '');
- var value = paramParts[1].replace(PARAM_TRIM_RE, '');
- if (key == "rel" && _contains(relations, value)) links[value] = url;
- });
- });
- }
-
- return links;
- },
-
- /**
- Parse server response data.
-
- This default implementation assumes the response data is in one of two
- structures:
-
- [
- {}, // Your new pagination state
- [{}, ...] // An array of JSON objects
- ]
-
- Or,
-
- [{}] // An array of JSON objects
-
- The first structure is the preferred form because the pagination states
- may have been updated on the server side, sending them down again allows
- this collection to update its states. If the response has a pagination
- state object, it is checked for errors.
-
- The second structure is the
- [Backbone.Collection#parse](http://backbonejs.org/#Collection-parse)
- default.
-
- **Note:** this method has been further simplified since 1.1.7. While
- existing #parse implementations will continue to work, new code is
- encouraged to override #parseState and #parseRecords instead.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} the options for the ajax request
-
- @return {Array.<Object>} An array of model objects
- */
- parse: function (resp, options) {
- var newState = this.parseState(resp, _clone(this.queryParams), _clone(this.state), options);
- if (newState) this.state = this._checkState(_extend({}, this.state, newState));
- return this.parseRecords(resp, options);
- },
-
- /**
- Parse server response for server pagination state updates. Not applicable
- under infinite mode.
-
- This default implementation first checks whether the response has any
- state object as documented in #parse. If it exists, a state object is
- returned by mapping the server state keys to this pageable collection
- instance's query parameter keys using `queryParams`.
-
- It is __NOT__ neccessary to return a full state object complete with all
- the mappings defined in #queryParams. Any state object resulted is merged
- with a copy of the current pageable collection state and checked for
- sanity before actually updating. Most of the time, simply providing a new
- `totalRecords` value is enough to trigger a full pagination state
- recalculation.
-
- parseState: function (resp, queryParams, state, options) {
- return {totalRecords: resp.total_entries};
- }
-
- If you want to use header fields use:
-
- parseState: function (resp, queryParams, state, options) {
- return {totalRecords: options.xhr.getResponseHeader("X-total")};
- }
-
- This method __MUST__ return a new state object instead of directly
- modifying the #state object. The behavior of directly modifying #state is
- undefined.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} queryParams A copy of #queryParams.
- @param {Object} state A copy of #state.
- @param {Object} [options] The options passed through from
- `parse`. (backbone >= 0.9.10 only)
-
- @return {Object} A new (partial) state object.
- */
- parseState: function (resp, queryParams, state, options) {
- if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
-
- var newState = _clone(state);
- var serverState = resp[0];
-
- _each(_pairs(_omit(queryParams, "directions")), function (kvp) {
- var k = kvp[0], v = kvp[1];
- var serverVal = serverState[v];
- if (!_isUndefined(serverVal) && !_.isNull(serverVal)) newState[k] = serverState[v];
- });
-
- if (serverState.order) {
- newState.order = _invert(queryParams.directions)[serverState.order] * 1;
- }
-
- return newState;
- }
- },
-
- /**
- Parse server response for an array of model objects.
-
- This default implementation first checks whether the response has any
- state object as documented in #parse. If it exists, the array of model
- objects is assumed to be the second element, otherwise the entire
- response is returned directly.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} [options] The options passed through from the
- `parse`. (backbone >= 0.9.10 only)
-
- @return {Array.<Object>} An array of model objects
- */
- parseRecords: function (resp, options) {
- if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
- return resp[1];
- }
-
- return resp;
- },
-
- /**
- Fetch a page from the server in server mode, or all the pages in client
- mode. Under infinite mode, the current page is refetched by default and
- then reset.
-
- The query string is constructed by translating the current pagination
- state to your server API query parameter using #queryParams. The current
- page will reset after fetch.
-
- @param {Object} [options] Accepts all
- [Backbone.Collection#fetch](http://backbonejs.org/#Collection-fetch)
- options.
-
- @return {XMLHttpRequest}
- */
- fetch: function (options) {
-
- options = options || {};
-
- var state = this._checkState(this.state);
-
- var mode = this.mode;
-
- if (mode == "infinite" && !options.url) {
- options.url = this.links[state.currentPage];
- }
-
- var data = options.data || {};
-
- // dedup query params
- var url = options.url || this.url || "";
- if (_isFunction(url)) url = url.call(this);
- var qsi = url.indexOf('?');
- if (qsi != -1) {
- _extend(data, queryStringToParams(url.slice(qsi + 1)));
- url = url.slice(0, qsi);
- }
-
- options.url = url;
- options.data = data;
-
- // map params except directions
- var queryParams = this.mode == "client" ?
- _pick(this.queryParams, "sortKey", "order") :
- _omit(_pick(this.queryParams, _keys(PageableProto.queryParams)),
- "directions");
-
- var i, kvp, k, v, kvps = _pairs(queryParams), thisCopy = _clone(this);
- for (i = 0; i < kvps.length; i++) {
- kvp = kvps[i], k = kvp[0], v = kvp[1];
- v = _isFunction(v) ? v.call(thisCopy) : v;
- if (state[k] != null && v != null) {
- data[v] = state[k];
- }
- }
-
- // fix up sorting parameters
- if (state.sortKey && state.order) {
- var o = _isFunction(queryParams.order) ?
- queryParams.order.call(thisCopy) :
- queryParams.order;
- data[o] = this.queryParams.directions[state.order + ""];
- }
- else if (!state.sortKey) delete data[queryParams.order];
-
- // map extra query parameters
- var extraKvps = _pairs(_omit(this.queryParams,
- _keys(PageableProto.queryParams)));
- for (i = 0; i < extraKvps.length; i++) {
- kvp = extraKvps[i];
- v = kvp[1];
- v = _isFunction(v) ? v.call(thisCopy) : v;
- if (v != null) data[kvp[0]] = v;
- }
-
- if (mode != "server") {
- var self = this, fullCol = this.fullCollection;
- var success = options.success;
- options.success = function (col, resp, opts) {
-
- // make sure the caller's intent is obeyed
- opts = opts || {};
- if (_isUndefined(options.silent)) delete opts.silent;
- else opts.silent = options.silent;
-
- var models = col.models;
- if (mode == "client") fullCol.reset(models, opts);
- else {
- fullCol.add(models, _extend({at: fullCol.length},
- _extend(opts, {parse: false})));
- self.trigger("reset", self, opts);
- }
-
- if (success) success(col, resp, opts);
- };
-
- // silent the first reset from backbone
- return BBColProto.fetch.call(this, _extend({}, options, {silent: true}));
- }
-
- return BBColProto.fetch.call(this, options);
- },
-
- /**
- Convenient method for making a `comparator` sorted by a model attribute
- identified by `sortKey` and ordered by `order`.
-
- Like a Backbone.Collection, a Backbone.PageableCollection will maintain
- the __current page__ in sorted order on the client side if a `comparator`
- is attached to it. If the collection is in client mode, you can attach a
- comparator to #fullCollection to have all the pages reflect the global
- sorting order by specifying an option `full` to `true`. You __must__ call
- `sort` manually or #fullCollection.sort after calling this method to
- force a resort.
-
- While you can use this method to sort the current page in server mode,
- the sorting order may not reflect the global sorting order due to the
- additions or removals of the records on the server since the last
- fetch. If you want the most updated page in a global sorting order, it is
- recommended that you set #state.sortKey and optionally #state.order, and
- then call #fetch.
-
- @protected
-
- @param {string} [sortKey=this.state.sortKey] See `state.sortKey`.
- @param {number} [order=this.state.order] See `state.order`.
- @param {(function(Backbone.Model, string): Object) | string} [sortValue] See #setSorting.
-
- See [Backbone.Collection.comparator](http://backbonejs.org/#Collection-comparator).
- */
- _makeComparator: function (sortKey, order, sortValue) {
- var state = this.state;
-
- sortKey = sortKey || state.sortKey;
- order = order || state.order;
-
- if (!sortKey || !order) return;
-
- if (!sortValue) sortValue = function (model, attr) {
- return model.get(attr);
- };
-
- return function (left, right) {
- var l = sortValue(left, sortKey), r = sortValue(right, sortKey), t;
- if (order === 1) t = l, l = r, r = t;
- if (l === r) return 0;
- else if (l < r) return -1;
- return 1;
- };
- },
-
- /**
- Adjusts the sorting for this pageable collection.
-
- Given a `sortKey` and an `order`, sets `state.sortKey` and
- `state.order`. A comparator can be applied on the client side to sort in
- the order defined if `options.side` is `"client"`. By default the
- comparator is applied to the #fullCollection. Set `options.full` to
- `false` to apply a comparator to the current page under any mode. Setting
- `sortKey` to `null` removes the comparator from both the current page and
- the full collection.
-
- If a `sortValue` function is given, it will be passed the `(model,
- sortKey)` arguments and is used to extract a value from the model during
- comparison sorts. If `sortValue` is not given, `model.get(sortKey)` is
- used for sorting.
-
- @chainable
-
- @param {string} sortKey See `state.sortKey`.
- @param {number} [order=this.state.order] See `state.order`.
- @param {Object} [options]
- @param {"server"|"client"} [options.side] By default, `"client"` if
- `mode` is `"client"`, `"server"` otherwise.
- @param {boolean} [options.full=true]
- @param {(function(Backbone.Model, string): Object) | string} [options.sortValue]
- */
- setSorting: function (sortKey, order, options) {
-
- var state = this.state;
-
- state.sortKey = sortKey;
- state.order = order = order || state.order;
-
- var fullCollection = this.fullCollection;
-
- var delComp = false, delFullComp = false;
-
- if (!sortKey) delComp = delFullComp = true;
-
- var mode = this.mode;
- options = _extend({side: mode == "client" ? mode : "server", full: true},
- options);
-
- var comparator = this._makeComparator(sortKey, order, options.sortValue);
-
- var full = options.full, side = options.side;
-
- if (side == "client") {
- if (full) {
- if (fullCollection) fullCollection.comparator = comparator;
- delComp = true;
- }
- else {
- this.comparator = comparator;
- delFullComp = true;
- }
- }
- else if (side == "server" && !full) {
- this.comparator = comparator;
- }
-
- if (delComp) this.comparator = null;
- if (delFullComp && fullCollection) fullCollection.comparator = null;
-
- return this;
- }
-
- });
-
- var PageableProto = PageableCollection.prototype;
-
- return PageableCollection;
-
-}));
[02/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.js b/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.js
deleted file mode 100644
index a27667f..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.standalone.js
+++ /dev/null
@@ -1,1860 +0,0 @@
-/**
- * rome - Customizable date (and time) picker. Opt-in UI, no jQuery!
- * @version v2.1.0
- * @link https://github.com/bevacqua/rome
- * @license MIT
- */
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.rome=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-
-process.nextTick = (function () {
- var canSetImmediate = typeof window !== 'undefined'
- && window.setImmediate;
- var canPost = typeof window !== 'undefined'
- && window.postMessage && window.addEventListener
- ;
-
- if (canSetImmediate) {
- return function (f) { return window.setImmediate(f) };
- }
-
- if (canPost) {
- var queue = [];
- window.addEventListener('message', function (ev) {
- var source = ev.source;
- if ((source === window || source === null) && ev.data === 'process-tick') {
- ev.stopPropagation();
- if (queue.length > 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
-
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
- }
-
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
-})();
-
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-
-function noop() {}
-
-process.on = noop;
-process.addListener = noop;
-process.once = noop;
-process.off = noop;
-process.removeListener = noop;
-process.removeAllListeners = noop;
-process.emit = noop;
-
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-}
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-
-},{}],2:[function(_dereq_,module,exports){
-module.exports = _dereq_('./src/contra.emitter.js');
-
-},{"./src/contra.emitter.js":3}],3:[function(_dereq_,module,exports){
-(function (process){
-(function (root, undefined) {
- 'use strict';
-
- var undef = '' + undefined;
- function atoa (a, n) { return Array.prototype.slice.call(a, n); }
- function debounce (fn, args, ctx) { if (!fn) { return; } tick(function run () { fn.apply(ctx || null, args || []); }); }
-
- // cross-platform ticker
- var si = typeof setImmediate === 'function', tick;
- if (si) {
- tick = function (fn) { setImmediate(fn); };
- } else if (typeof process !== undef && process.nextTick) {
- tick = process.nextTick;
- } else {
- tick = function (fn) { setTimeout(fn, 0); };
- }
-
- function _emitter (thing, options) {
- var opts = options || {};
- var evt = {};
- if (thing === undefined) { thing = {}; }
- thing.on = function (type, fn) {
- if (!evt[type]) {
- evt[type] = [fn];
- } else {
- evt[type].push(fn);
- }
- return thing;
- };
- thing.once = function (type, fn) {
- fn._once = true; // thing.off(fn) still works!
- thing.on(type, fn);
- return thing;
- };
- thing.off = function (type, fn) {
- var c = arguments.length;
- if (c === 1) {
- delete evt[type];
- } else if (c === 0) {
- evt = {};
- } else {
- var et = evt[type];
- if (!et) { return thing; }
- et.splice(et.indexOf(fn), 1);
- }
- return thing;
- };
- thing.emit = function () {
- var args = atoa(arguments);
- return thing.emitterSnapshot(args.shift()).apply(this, args);
- };
- thing.emitterSnapshot = function (type) {
- var et = (evt[type] || []).slice(0);
- return function () {
- var args = atoa(arguments);
- var ctx = this || thing;
- if (type === 'error' && opts.throws !== false && !et.length) { throw args.length === 1 ? args[0] : args; }
- evt[type] = et.filter(function emitter (listen) {
- if (opts.async) { debounce(listen, args, ctx); } else { listen.apply(ctx, args); }
- return !listen._once;
- });
- return thing;
- };
- }
- return thing;
- }
-
- // cross-platform export
- if (typeof module !== undef && module.exports) {
- module.exports = _emitter;
- } else {
- root.contra = root.contra || {};
- root.contra.emitter = _emitter;
- }
-})(this);
-
-}).call(this,_dereq_("FWaASH"))
-},{"FWaASH":1}],4:[function(_dereq_,module,exports){
-var now = _dereq_('performance-now')
- , global = typeof window === 'undefined' ? {} : window
- , vendors = ['moz', 'webkit']
- , suffix = 'AnimationFrame'
- , raf = global['request' + suffix]
- , caf = global['cancel' + suffix] || global['cancelRequest' + suffix]
- , isNative = true
-
-for(var i = 0; i < vendors.length && !raf; i++) {
- raf = global[vendors[i] + 'Request' + suffix]
- caf = global[vendors[i] + 'Cancel' + suffix]
- || global[vendors[i] + 'CancelRequest' + suffix]
-}
-
-// Some versions of FF have rAF but not cAF
-if(!raf || !caf) {
- isNative = false
-
- var last = 0
- , id = 0
- , queue = []
- , frameDuration = 1000 / 60
-
- raf = function(callback) {
- if(queue.length === 0) {
- var _now = now()
- , next = Math.max(0, frameDuration - (_now - last))
- last = next + _now
- setTimeout(function() {
- var cp = queue.slice(0)
- // Clear queue here to prevent
- // callbacks from appending listeners
- // to the current frame's queue
- queue.length = 0
- for(var i = 0; i < cp.length; i++) {
- if(!cp[i].cancelled) {
- try{
- cp[i].callback(last)
- } catch(e) {
- setTimeout(function() { throw e }, 0)
- }
- }
- }
- }, Math.round(next))
- }
- queue.push({
- handle: ++id,
- callback: callback,
- cancelled: false
- })
- return id
- }
-
- caf = function(handle) {
- for(var i = 0; i < queue.length; i++) {
- if(queue[i].handle === handle) {
- queue[i].cancelled = true
- }
- }
- }
-}
-
-module.exports = function(fn) {
- // Wrap in a new function to prevent
- // `cancel` potentially being assigned
- // to the native rAF function
- if(!isNative) {
- return raf.call(global, fn)
- }
- return raf.call(global, function() {
- try{
- fn.apply(this, arguments)
- } catch(e) {
- setTimeout(function() { throw e }, 0)
- }
- })
-}
-module.exports.cancel = function() {
- caf.apply(global, arguments)
-}
-
-},{"performance-now":5}],5:[function(_dereq_,module,exports){
-(function (process){
-// Generated by CoffeeScript 1.6.3
-(function() {
- var getNanoSeconds, hrtime, loadTime;
-
- if ((typeof performance !== "undefined" && performance !== null) && performance.now) {
- module.exports = function() {
- return performance.now();
- };
- } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) {
- module.exports = function() {
- return (getNanoSeconds() - loadTime) / 1e6;
- };
- hrtime = process.hrtime;
- getNanoSeconds = function() {
- var hr;
- hr = hrtime();
- return hr[0] * 1e9 + hr[1];
- };
- loadTime = getNanoSeconds();
- } else if (Date.now) {
- module.exports = function() {
- return Date.now() - loadTime;
- };
- loadTime = Date.now();
- } else {
- module.exports = function() {
- return new Date().getTime() - loadTime;
- };
- loadTime = new Date().getTime();
- }
-
-}).call(this);
-
-/*
-//@ sourceMappingURL=performance-now.map
-*/
-
-}).call(this,_dereq_("FWaASH"))
-},{"FWaASH":1}],6:[function(_dereq_,module,exports){
-'use strict';
-
-var isInput = _dereq_('./isInput');
-var bindings = {};
-
-function has (source, target) {
- var binding = bindings[source.id];
- return binding && binding[target.id];
-}
-
-function insert (source, target) {
- var binding = bindings[source.id];
- if (!binding) {
- binding = bindings[source.id] = {};
- }
- var invalidate = invalidator(target);
- binding[target.id] = invalidate;
- source.on('data', invalidate);
- source.on('destroyed', remove.bind(null, source, target));
-}
-
-function remove (source, target) {
- var binding = bindings[source.id];
- if (!binding) {
- return;
- }
- var invalidate = binding[target.id];
- source.off('data', invalidate);
- delete binding[target.id];
-}
-
-function invalidator (target) {
- return function invalidate () {
- target.refresh();
- };
-}
-
-function add (source, target) {
- if (isInput(target.associated) || has(source, target)) {
- return;
- }
- insert(source, target);
-}
-
-module.exports = {
- add: add,
- remove: remove
-};
-
-},{"./isInput":17}],7:[function(_dereq_,module,exports){
-'use strict';
-
-var emitter = _dereq_('contra.emitter');
-var raf = _dereq_('raf');
-var dom = _dereq_('./dom');
-var text = _dereq_('./text');
-var parse = _dereq_('./parse');
-var clone = _dereq_('./clone');
-var defaults = _dereq_('./defaults');
-var momentum = _dereq_('./momentum');
-var classes = _dereq_('./classes');
-var events = _dereq_('./events');
-var noop = _dereq_('./noop');
-var no;
-
-function calendar (calendarOptions) {
- var o;
- var api = emitter({});
- var ref;
- var refCal;
- var container;
- var rendered = false;
-
- // date variables
- var monthOffsetAttribute = 'data-rome-offset';
- var weekdays;
- var weekdayCount;
- var calendarMonths = [];
- var lastYear;
- var lastMonth;
- var lastDay;
- var lastDayElement;
- var datewrapper;
- var back;
- var next;
-
- // time variables
- var secondsInDay = 60 * 60 * 24;
- var time;
- var timelist;
-
- init();
- raf(ready);
-
- return api;
-
- function napi () { return api; }
-
- function init (initOptions) {
- o = defaults(initOptions || calendarOptions, api);
- if (!container) { container = dom({ className: o.styles.container }); }
- weekdays = o.weekdayFormat;
- weekdayCount = weekdays.length;
- lastMonth = no;
- lastYear = no;
- lastDay = no;
- lastDayElement = no;
- o.appendTo.appendChild(container);
-
- removeChildren(container);
- rendered = false;
- ref = o.initialValue ? o.initialValue : momentum.moment();
- refCal = ref.clone();
-
- api.container = container;
- api.destroyed = false;
- api.destroy = destroy.bind(api, false);
- api.emitValues = emitValues;
- api.getDate = getDate;
- api.getDateString = getDateString;
- api.getMoment = getMoment;
- api.hide = hide;
- api.options = changeOptions;
- api.options.reset = resetOptions;
- api.refresh = refresh;
- api.restore = napi;
- api.setValue = setValue;
- api.show = show;
-
- show();
- eventListening();
- ready();
-
- return api;
- }
-
- function ready () {
- api.emit('ready', clone(o));
- }
-
- function destroy (silent) {
- if (container) {
- container.parentNode.removeChild(container);
- }
-
- if (o) {
- eventListening(true);
- }
-
- var destroyed = api.emitterSnapshot('destroyed');
- api.destroyed = true;
- api.destroy = napi;
- api.emitValues = napi;
- api.getDate = noop;
- api.getDateString = noop;
- api.getMoment = noop;
- api.hide = napi;
- api.options = napi;
- api.options.reset = napi;
- api.refresh = napi;
- api.restore = init;
- api.setValue = napi;
- api.show = napi;
- api.off();
-
- if (silent !== true) {
- destroyed();
- }
-
- return api;
- }
-
- function eventListening (remove) {
- var op = remove ? 'remove' : 'add';
- if (o.autoHideOnBlur) { events[op](document.documentElement, 'focus', hideOnBlur, true); }
- if (o.autoHideOnClick) { events[op](document, 'click', hideOnClick); }
- }
-
- function changeOptions (options) {
- if (arguments.length === 0) {
- return clone(o);
- }
- destroy();
- init(options);
- return api;
- }
-
- function resetOptions () {
- return changeOptions({ appendTo: o.appendTo });
- }
-
- function render () {
- if (rendered) {
- return;
- }
- rendered = true;
- renderDates();
- renderTime();
- api.emit('render');
- }
-
- function renderDates () {
- if (!o.date) {
- return;
- }
- var i;
- calendarMonths = [];
-
- datewrapper = dom({ className: o.styles.date, parent: container });
-
- for (i = 0; i < o.monthsInCalendar; i++) {
- renderMonth(i);
- }
-
- events.add(back, 'click', subtractMonth);
- events.add(next, 'click', addMonth);
- events.add(datewrapper, 'click', pickDay);
-
- function renderMonth (i) {
- var month = dom({ className: o.styles.month, parent: datewrapper });
- if (i === 0) {
- back = dom({ type: 'button', className: o.styles.back, attributes: { type: 'button' }, parent: month });
- }
- if (i === o.monthsInCalendar -1) {
- next = dom({ type: 'button', className: o.styles.next, attributes: { type: 'button' }, parent: month });
- }
- var label = dom({ className: o.styles.monthLabel, parent: month });
- var date = dom({ type: 'table', className: o.styles.dayTable, parent: month });
- var datehead = dom({ type: 'thead', className: o.styles.dayHead, parent: date });
- var dateheadrow = dom({ type: 'tr', className: o.styles.dayRow, parent: datehead });
- var datebody = dom({ type: 'tbody', className: o.styles.dayBody, parent: date });
- var j;
-
- for (j = 0; j < weekdayCount; j++) {
- dom({ type: 'th', className: o.styles.dayHeadElem, parent: dateheadrow, text: weekdays[weekday(j)] });
- }
-
- datebody.setAttribute(monthOffsetAttribute, i);
- calendarMonths.push({
- label: label,
- body: datebody
- });
- }
- }
-
- function renderTime () {
- if (!o.time || !o.timeInterval) {
- return;
- }
- var timewrapper = dom({ className: o.styles.time, parent: container });
- time = dom({ className: o.styles.selectedTime, parent: timewrapper, text: ref.format(o.timeFormat) });
- events.add(time, 'click', toggleTimeList);
- timelist = dom({ className: o.styles.timeList, parent: timewrapper });
- events.add(timelist, 'click', pickTime);
- var next = momentum.moment('00:00:00', 'HH:mm:ss');
- var latest = next.clone().add(1, 'days');
- while (next.isBefore(latest)) {
- dom({ className: o.styles.timeOption, parent: timelist, text: next.format(o.timeFormat) });
- next.add(o.timeInterval, 'seconds');
- }
- }
-
- function weekday (index, backwards) {
- var factor = backwards ? -1 : 1;
- var offset = index + o.weekStart * factor;
- if (offset >= weekdayCount || offset < 0) {
- offset += weekdayCount * -factor;
- }
- return offset;
- }
-
- function displayValidTimesOnly () {
- if (!o.time || !rendered) {
- return;
- }
- var times = timelist.children;
- var length = times.length;
- var date;
- var time;
- var item;
- var i;
- for (i = 0; i < length; i++) {
- item = times[i];
- time = momentum.moment(text(item), o.timeFormat);
- date = setTime(ref.clone(), time);
- item.style.display = isInRange(date, false, o.timeValidator) ? 'block' : 'none';
- }
- }
-
- function toggleTimeList (show) {
- var display = typeof show === 'boolean' ? show : timelist.style.display === 'none';
- if (display) {
- showTimeList();
- } else {
- hideTimeList();
- }
- }
-
- function showTimeList () { if (timelist) { timelist.style.display = 'block'; } }
- function hideTimeList () { if (timelist) { timelist.style.display = 'none'; } }
- function showCalendar () { container.style.display = 'inline-block'; api.emit('show'); }
- function hideCalendar () { container.style.display = 'none'; api.emit('hide'); }
-
- function show () {
- render();
- refresh();
- toggleTimeList(!o.date);
- showCalendar();
- return api;
- }
-
- function hide () {
- hideTimeList();
- raf(hideCalendar);
- return api;
- }
-
- function hideConditionally () {
- hideTimeList();
-
- var pos = classes.contains(container, o.styles.positioned);
- if (pos) {
- raf(hideCalendar);
- }
- return api;
- }
-
- function calendarEventTarget (e) {
- var target = e.target;
- if (target === api.associated) {
- return true;
- }
- while (target) {
- if (target === container) {
- return true;
- }
- target = target.parentNode;
- }
- }
-
- function hideOnBlur (e) {
- if (calendarEventTarget(e)) {
- return;
- }
- hideConditionally();
- }
-
- function hideOnClick (e) {
- if (calendarEventTarget(e)) {
- return;
- }
- hideConditionally();
- }
-
- function subtractMonth () { changeMonth('subtract'); }
- function addMonth () { changeMonth('add'); }
- function changeMonth (op) {
- var bound;
- var direction = op === 'add' ? -1 : 1;
- var offset = o.monthsInCalendar + direction * getMonthOffset(lastDayElement);
- refCal[op](offset, 'months');
- bound = inRange(refCal.clone());
- ref = bound || ref;
- if (bound) { refCal = bound.clone(); }
- update();
- }
-
- function update (silent) {
- updateCalendar();
- updateTime();
- if (silent !== true) { emitValues(); }
- displayValidTimesOnly();
- }
-
- function updateCalendar () {
- if (!o.date || !rendered) {
- return;
- }
- var y = refCal.year();
- var m = refCal.month();
- var d = refCal.date();
- if (d === lastDay && m === lastMonth && y === lastYear) {
- return;
- }
- var canStay = isDisplayed();
- lastDay = refCal.date();
- lastMonth = refCal.month();
- lastYear = refCal.year();
- if (canStay) { updateCalendarSelection(); return; }
- calendarMonths.forEach(updateMonth);
- renderAllDays();
-
- function updateMonth (month, i) {
- var offsetCal = refCal.clone().add(i, 'months');
- text(month.label, offsetCal.format(o.monthFormat));
- removeChildren(month.body);
- }
- }
-
- function updateCalendarSelection () {
- var day = refCal.date() - 1;
- selectDayElement(false);
- calendarMonths.forEach(function (cal) {
- var days;
- if (sameCalendarMonth(cal.date, refCal)) {
- days = cast(cal.body.children).map(aggregate);
- days = Array.prototype.concat.apply([], days).filter(inside);
- selectDayElement(days[day]);
- }
- });
-
- function cast (like) {
- var dest = [];
- var i;
- for (i = 0; i < like.length; i++) {
- dest.push(like[i]);
- }
- return dest;
- }
-
- function aggregate (child) {
- return cast(child.children);
- }
-
- function inside (child) {
- return !classes.contains(child, o.styles.dayPrevMonth) &&
- !classes.contains(child, o.styles.dayNextMonth);
- }
- }
-
- function isDisplayed () {
- return calendarMonths.some(matches);
-
- function matches (cal) {
- if (!lastYear) { return false; }
- return sameCalendarMonth(cal.date, refCal);
- }
- }
-
- function sameCalendarMonth (left, right) {
- return left && right && left.year() === right.year() && left.month() === right.month();
- }
-
- function updateTime () {
- if (!o.time || !rendered) {
- return;
- }
- text(time, ref.format(o.timeFormat));
- }
-
- function emitValues () {
- api.emit('data', getDateString());
- api.emit('year', ref.year());
- api.emit('month', ref.month());
- api.emit('day', ref.day());
- api.emit('time', ref.format(o.timeFormat));
- return api;
- }
-
- function refresh () {
- lastYear = false;
- lastMonth = false;
- lastDay = false;
- update(true);
- return api;
- }
-
- function setValue (value) {
- var date = parse(value, o.inputFormat);
- if (date === null) {
- return;
- }
- ref = inRange(date) || ref;
- refCal = ref.clone();
- update(true);
-
- return api;
- }
-
- function removeChildren (elem, self) {
- while (elem && elem.firstChild) {
- elem.removeChild(elem.firstChild);
- }
- if (self === true) {
- elem.parentNode.removeChild(elem);
- }
- }
-
- function renderAllDays () {
- var i;
- for (i = 0; i < o.monthsInCalendar; i++) {
- renderDays(i);
- }
- }
-
- function renderDays (offset) {
- var month = calendarMonths[offset];
- var offsetCal = refCal.clone().add(offset, 'months');
- var total = offsetCal.daysInMonth();
- var current = offsetCal.month() !== ref.month() ? -1 : ref.date(); // -1 : 1..31
- var first = offsetCal.clone().date(1);
- var firstDay = weekday(first.day(), true); // 0..6
- var tr = dom({ type: 'tr', className: o.styles.dayRow, parent: month.body });
- var prevMonth = hiddenWhen(offset !== 0, [o.styles.dayBodyElem, o.styles.dayPrevMonth]);
- var nextMonth = hiddenWhen(offset !== o.monthsInCalendar - 1, [o.styles.dayBodyElem, o.styles.dayNextMonth]);
- var disabled = o.styles.dayDisabled;
- var lastDay;
-
- part({
- base: first.clone().subtract(firstDay, 'days'),
- length: firstDay,
- cell: prevMonth
- });
-
- part({
- base: first.clone(),
- length: total,
- cell: [o.styles.dayBodyElem],
- selectable: true
- });
-
- lastDay = first.clone().add(total, 'days');
-
- part({
- base: lastDay,
- length: weekdayCount - tr.children.length,
- cell: nextMonth
- });
-
- back.disabled = !isInRangeLeft(first, true);
- next.disabled = !isInRangeRight(lastDay, true);
- month.date = offsetCal.clone();
-
- function part (data) {
- var i, day, node;
- for (i = 0; i < data.length; i++) {
- if (tr.children.length === weekdayCount) {
- tr = dom({ type: 'tr', className: o.styles.dayRow, parent: month.body });
- }
- day = data.base.clone().add(i, 'days');
- node = dom({
- type: 'td',
- parent: tr,
- text: day.format(o.dayFormat),
- className: validationTest(day, data.cell.join(' ').split(' ')).join(' ')
- });
- if (data.selectable && day.date() === current) {
- selectDayElement(node);
- }
- }
- }
-
- function validationTest (day, cell) {
- if (!isInRange(day, true, o.dateValidator)) { cell.push(disabled); }
- return cell;
- }
-
- function hiddenWhen (value, cell) {
- if (value) { cell.push(o.styles.dayConcealed); }
- return cell;
- }
- }
-
- function isInRange (date, allday, validator) {
- if (!isInRangeLeft(date, allday)) {
- return false;
- }
- if (!isInRangeRight(date, allday)) {
- return false;
- }
- var valid = (validator || Function.prototype).call(api, date.toDate());
- return valid !== false;
- }
-
- function isInRangeLeft (date, allday) {
- var min = !o.min ? false : (allday ? o.min.clone().startOf('day') : o.min);
- return !min || !date.isBefore(min);
- }
-
- function isInRangeRight (date, allday) {
- var max = !o.max ? false : (allday ? o.max.clone().endOf('day') : o.max);
- return !max || !date.isAfter(max);
- }
-
- function inRange (date) {
- if (o.min && date.isBefore(o.min)) {
- return inRange(o.min.clone());
- } else if (o.max && date.isAfter(o.max)) {
- return inRange(o.max.clone());
- }
- var value = date.clone().subtract(1, 'days');
- if (validateTowards(value, date, 'add')) {
- return inTimeRange(value);
- }
- value = date.clone();
- if (validateTowards(value, date, 'subtract')) {
- return inTimeRange(value);
- }
- }
-
- function inTimeRange (value) {
- var copy = value.clone().subtract(o.timeInterval, 'seconds');
- var times = Math.ceil(secondsInDay / o.timeInterval);
- var i;
- for (i = 0; i < times; i++) {
- copy.add(o.timeInterval, 'seconds');
- if (copy.date() > value.date()) {
- copy.subtract(1, 'days');
- }
- if (o.timeValidator.call(api, copy.toDate()) !== false) {
- return copy;
- }
- }
- }
-
- function validateTowards (value, date, op) {
- var valid = false;
- while (valid === false) {
- value[op](1, 'days');
- if (value.month() !== date.month()) {
- break;
- }
- valid = o.dateValidator.call(api, value.toDate());
- }
- return valid !== false;
- }
-
- function pickDay (e) {
- var target = e.target;
- if (classes.contains(target, o.styles.dayDisabled) || !classes.contains(target, o.styles.dayBodyElem)) {
- return;
- }
- var day = parseInt(text(target), 10);
- var prev = classes.contains(target, o.styles.dayPrevMonth);
- var next = classes.contains(target, o.styles.dayNextMonth);
- var offset = getMonthOffset(target) - getMonthOffset(lastDayElement);
- ref.add(offset, 'months');
- if (prev || next) {
- ref.add(prev ? -1 : 1, 'months');
- }
- selectDayElement(target);
- ref.date(day); // must run after setting the month
- setTime(ref, inRange(ref) || ref);
- refCal = ref.clone();
- if (o.autoClose === true) { hideConditionally(); }
- update();
- }
-
- function selectDayElement (node) {
- if (lastDayElement) {
- classes.remove(lastDayElement, o.styles.selectedDay);
- }
- if (node) {
- classes.add(node, o.styles.selectedDay);
- }
- lastDayElement = node;
- }
-
- function getMonthOffset (elem) {
- var offset;
- while (elem && elem.getAttribute) {
- offset = elem.getAttribute(monthOffsetAttribute);
- if (typeof offset === 'string') {
- return parseInt(offset, 10);
- }
- elem = elem.parentNode;
- }
- return 0;
- }
-
- function setTime (to, from) {
- to.hour(from.hour()).minute(from.minute()).second(from.second());
- return to;
- }
-
- function pickTime (e) {
- var target = e.target;
- if (!classes.contains(target, o.styles.timeOption)) {
- return;
- }
- var value = momentum.moment(text(target), o.timeFormat);
- setTime(ref, value);
- refCal = ref.clone();
- emitValues();
- updateTime();
- if ((!o.date && o.autoClose === true) || o.autoClose === 'time') {
- hideConditionally();
- } else {
- hideTimeList();
- }
- }
-
- function getDate () {
- return ref.toDate();
- }
-
- function getDateString (format) {
- return ref.format(format || o.inputFormat);
- }
-
- function getMoment () {
- return ref.clone();
- }
-}
-
-module.exports = calendar;
-
-},{"./classes":8,"./clone":9,"./defaults":11,"./dom":12,"./events":13,"./momentum":18,"./noop":19,"./parse":20,"./text":32,"contra.emitter":2,"raf":4}],8:[function(_dereq_,module,exports){
-'use strict';
-
-var trim = /^\s+|\s+$/g;
-var whitespace = /\s+/;
-
-function classes (node) {
- return node.className.replace(trim, '').split(whitespace);
-}
-
-function set (node, value) {
- node.className = value.join(' ');
-}
-
-function add (node, value) {
- var values = remove(node, value);
- values.push(value);
- set(node, values);
-}
-
-function remove (node, value) {
- var values = classes(node);
- var i = values.indexOf(value);
- if (i !== -1) {
- values.splice(i, 1);
- set(node, values);
- }
- return values;
-}
-
-function contains (node, value) {
- return classes(node).indexOf(value) !== -1;
-}
-
-module.exports = {
- add: add,
- remove: remove,
- contains: contains
-};
-
-},{}],9:[function(_dereq_,module,exports){
-'use strict';
-
-var momentum = _dereq_('./momentum');
-
-// naïve implementation, specifically meant to clone `options` objects
-function clone (thing) {
- var copy = {};
- var value;
-
- for (var key in thing) {
- value = thing[key];
-
- if (!value) {
- copy[key] = value;
- } else if (momentum.isMoment(value)) {
- copy[key] = value.clone();
- } else if (value._isStylesConfiguration) {
- copy[key] = clone(value);
- } else {
- copy[key] = value;
- }
- }
-
- return copy;
-}
-
-module.exports = clone;
-
-},{"./momentum":18}],10:[function(_dereq_,module,exports){
-'use strict';
-
-var index = _dereq_('./index');
-var input = _dereq_('./input');
-var inline = _dereq_('./inline');
-var isInput = _dereq_('./isInput');
-
-function core (elem, options) {
- var cal;
- var existing = index.find(elem);
- if (existing) {
- return existing;
- }
-
- if (isInput(elem)) {
- cal = input(elem, options);
- } else {
- cal = inline(elem, options);
- }
- cal.associated = elem;
- index.assign(elem, cal);
-
- return cal;
-}
-
-module.exports = core;
-
-},{"./index":14,"./inline":15,"./input":16,"./isInput":17}],11:[function(_dereq_,module,exports){
-'use strict';
-
-var parse = _dereq_('./parse');
-var isInput = _dereq_('./isInput');
-var momentum = _dereq_('./momentum');
-
-function defaults (options, cal) {
- var temp;
- var no;
- var o = options || {};
- if (o.autoHideOnClick === no) { o.autoHideOnClick = true; }
- if (o.autoHideOnBlur === no) { o.autoHideOnBlur = true; }
- if (o.autoClose === no) { o.autoClose = true; }
- if (o.appendTo === no) { o.appendTo = document.body; }
- if (o.appendTo === 'parent') {
- if (isInput(cal.associated)) {
- o.appendTo = cal.associated.parentNode;
- } else {
- throw new Error('Inline calendars must be appended to a parent node explicitly.');
- }
- }
- if (o.invalidate === no) { o.invalidate = true; }
- if (o.required === no) { o.required = false; }
- if (o.date === no) { o.date = true; }
- if (o.time === no) { o.time = true; }
- if (o.date === false && o.time === false) { throw new Error('At least one of `date` or `time` must be `true`.'); }
- if (o.inputFormat === no) {
- if (o.date && o.time) {
- o.inputFormat = 'YYYY-MM-DD HH:mm';
- } else if (o.date) {
- o.inputFormat = 'YYYY-MM-DD';
- } else {
- o.inputFormat = 'HH:mm';
- }
- }
- if (o.initialValue === no) {
- o.initialValue = null;
- } else {
- o.initialValue = parse(o.initialValue, o.inputFormat);
- }
- if (o.min === no) { o.min = null; } else { o.min = parse(o.min, o.inputFormat); }
- if (o.max === no) { o.max = null; } else { o.max = parse(o.max, o.inputFormat); }
- if (o.timeInterval === no) { o.timeInterval = 60 * 30; } // 30 minutes by default
- if (o.min && o.max) {
- if (o.max.isBefore(o.min)) {
- temp = o.max;
- o.max = o.min;
- o.min = temp;
- }
- if (o.date === true) {
- if (o.max.clone().subtract(1, 'days').isBefore(o.min)) {
- throw new Error('`max` must be at least one day after `min`');
- }
- } else if (o.timeInterval * 1000 - o.min % (o.timeInterval * 1000) > o.max - o.min) {
- throw new Error('`min` to `max` range must allow for at least one time option that matches `timeInterval`');
- }
- }
- if (o.dateValidator === no) { o.dateValidator = Function.prototype; }
- if (o.timeValidator === no) { o.timeValidator = Function.prototype; }
- if (o.timeFormat === no) { o.timeFormat = 'HH:mm'; }
- if (o.weekStart === no) { o.weekStart = momentum.moment().weekday(0).day(); }
- if (o.weekdayFormat === no) { o.weekdayFormat = 'min'; }
- if (o.weekdayFormat === 'long') {
- o.weekdayFormat = momentum.moment.weekdays();
- } else if (o.weekdayFormat === 'short') {
- o.weekdayFormat = momentum.moment.weekdaysShort();
- } else if (o.weekdayFormat === 'min') {
- o.weekdayFormat = momentum.moment.weekdaysMin();
- } else if (!Array.isArray(o.weekdayFormat) || o.weekdayFormat.length < 7) {
- throw new Error('`weekdays` must be `min`, `short`, or `long`');
- }
- if (o.monthsInCalendar === no) { o.monthsInCalendar = 1; }
- if (o.monthFormat === no) { o.monthFormat = 'MMMM YYYY'; }
- if (o.dayFormat === no) { o.dayFormat = 'DD'; }
- if (o.styles === no) { o.styles = {}; }
-
- o.styles._isStylesConfiguration = true;
-
- var styl = o.styles;
- if (styl.back === no) { styl.back = 'rd-back'; }
- if (styl.container === no) { styl.container = 'rd-container'; }
- if (styl.positioned === no) { styl.positioned = 'rd-container-attachment'; }
- if (styl.date === no) { styl.date = 'rd-date'; }
- if (styl.dayBody === no) { styl.dayBody = 'rd-days-body'; }
- if (styl.dayBodyElem === no) { styl.dayBodyElem = 'rd-day-body'; }
- if (styl.dayPrevMonth === no) { styl.dayPrevMonth = 'rd-day-prev-month'; }
- if (styl.dayNextMonth === no) { styl.dayNextMonth = 'rd-day-next-month'; }
- if (styl.dayDisabled === no) { styl.dayDisabled = 'rd-day-disabled'; }
- if (styl.dayConcealed === no) { styl.dayConcealed = 'rd-day-concealed'; }
- if (styl.dayHead === no) { styl.dayHead = 'rd-days-head'; }
- if (styl.dayHeadElem === no) { styl.dayHeadElem = 'rd-day-head'; }
- if (styl.dayRow === no) { styl.dayRow = 'rd-days-row'; }
- if (styl.dayTable === no) { styl.dayTable = 'rd-days'; }
- if (styl.month === no) { styl.month = 'rd-month'; }
- if (styl.monthLabel === no) { styl.monthLabel = 'rd-month-label'; }
- if (styl.next === no) { styl.next = 'rd-next'; }
- if (styl.selectedDay === no) { styl.selectedDay = 'rd-day-selected'; }
- if (styl.selectedTime === no) { styl.selectedTime = 'rd-time-selected'; }
- if (styl.time === no) { styl.time = 'rd-time'; }
- if (styl.timeList === no) { styl.timeList = 'rd-time-list'; }
- if (styl.timeOption === no) { styl.timeOption = 'rd-time-option'; }
-
- return o;
-}
-
-module.exports = defaults;
-
-},{"./isInput":17,"./momentum":18,"./parse":20}],12:[function(_dereq_,module,exports){
-'use strict';
-
-function dom (options) {
- var o = options || {};
- if (!o.type) { o.type = 'div'; }
- var elem = document.createElement(o.type);
- if (o.className) { elem.className = o.className; }
- if (o.text) { elem.innerText = elem.textContent = o.text; }
- if (o.attributes) {
- Object.keys(o.attributes).forEach(function(key) {
- elem.setAttribute(key, o.attributes[key]);
- });
- }
- if (o.parent) { o.parent.appendChild(elem); }
- return elem;
-}
-
-module.exports = dom;
-
-},{}],13:[function(_dereq_,module,exports){
-'use strict';
-
-var addEvent = addEventEasy;
-var removeEvent = removeEventEasy;
-
-if (!window.addEventListener) {
- addEvent = addEventHard;
-}
-
-if (!window.removeEventListener) {
- removeEvent = removeEventHard;
-}
-
-function addEventEasy (element, evt, fn, capture) {
- return element.addEventListener(evt, fn, capture);
-}
-
-function addEventHard (element, evt, fn, capture) {
- return element.attachEvent('on' + evt, function (ae) {
- var e = ae || window.event;
- e.target = e.target || e.srcElement;
- e.preventDefault = e.preventDefault || function preventDefault () { e.returnValue = false; };
- e.stopPropagation = e.stopPropagation || function stopPropagation () { e.cancelBubble = true; };
- fn.call(element, e);
- }, capture);
-}
-
-function removeEventEasy (element, evt, fn) {
- return element.removeEventListener(evt, fn);
-}
-
-function removeEventHard (element, evt, fn) {
- return element.detachEvent('on' + evt, fn);
-}
-
-module.exports = {
- add: addEvent,
- remove: removeEvent
-};
-
-},{}],14:[function(_dereq_,module,exports){
-'use strict';
-var no;
-var ikey = 'data-rome-id';
-var index = [];
-
-function find (thing) { // can be a DOM element or a number
- if (typeof thing !== 'number' && thing && thing.getAttribute) {
- return find(thing.getAttribute(ikey));
- }
- var existing = index[thing];
- if (existing !== no) {
- return existing;
- }
- return null;
-}
-
-function assign (elem, instance) {
- elem.setAttribute(ikey, instance.id = index.push(instance) - 1);
-}
-
-module.exports = {
- find: find,
- assign: assign
-};
-
-},{}],15:[function(_dereq_,module,exports){
-'use strict';
-
-var raf = _dereq_('raf');
-var calendar = _dereq_('./calendar');
-
-function inline (elem, calendarOptions) {
- var o = calendarOptions || {};
-
- o.appendTo = elem;
-
- return calendar(o);
-}
-
-module.exports = inline;
-
-},{"./calendar":7,"raf":4}],16:[function(_dereq_,module,exports){
-'use strict';
-
-var throttle = _dereq_('./throttle');
-var raf = _dereq_('raf');
-var clone = _dereq_('./clone');
-var defaults = _dereq_('./defaults');
-var calendar = _dereq_('./calendar');
-var momentum = _dereq_('./momentum');
-var classes = _dereq_('./classes');
-var events = _dereq_('./events');
-
-function inputCalendar (input, calendarOptions) {
- var o;
- var api = calendar(calendarOptions);
- var throttledTakeInput = throttle(takeInput, 30);
- var throttledPosition = throttle(position, 30);
- var ignoreInvalidation;
- var ignoreShow;
-
- init(calendarOptions);
-
- return api;
-
- function init (initOptions) {
- o = defaults(initOptions || calendarOptions, api);
-
- classes.add(api.container, o.styles.positioned);
- events.add(api.container, 'mousedown', containerMouseDown);
- events.add(api.container, 'click', containerClick);
-
- api.getDate = unrequire(api.getDate);
- api.getDateString = unrequire(api.getDateString);
- api.getMoment = unrequire(api.getMoment);
-
- if (o.initialValue) {
- input.value = o.initialValue.format(o.inputFormat);
- }
-
- api.on('data', updateInput);
- api.on('show', throttledPosition);
-
- eventListening();
- throttledTakeInput();
-
- api.hide();
- }
-
- function destroy () {
- eventListening(true);
- }
-
- function eventListening (remove) {
- var op = remove ? 'remove' : 'add';
- events[op](input, 'click', show);
- events[op](input, 'touchend', show);
- events[op](input, 'focusin', show);
- events[op](input, 'change', throttledTakeInput);
- events[op](input, 'keypress', throttledTakeInput);
- events[op](input, 'keydown', throttledTakeInput);
- events[op](input, 'input', throttledTakeInput);
- if (o.invalidate) { events[op](input, 'blur', invalidateInput); }
- events[op](window, 'resize', throttledPosition);
-
- if (remove) {
- api.once('ready', init);
- api.off('destroyed', destroy);
- } else {
- api.off('ready', init);
- api.once('destroyed', destroy);
- }
- }
-
- function containerClick () {
- ignoreShow = true;
- input.focus();
- ignoreShow = false;
- }
-
- function containerMouseDown () {
- ignoreInvalidation = true;
- raf(unignore);
-
- function unignore () {
- ignoreInvalidation = false;
- }
- }
-
- function invalidateInput () {
- if (!ignoreInvalidation && !isEmpty()) {
- api.emitValues();
- }
- }
-
- function show () {
- if (ignoreShow) {
- return;
- }
- api.show();
- }
-
- function position () {
- var bounds = input.getBoundingClientRect();
- var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
- api.container.style.top = bounds.top + scrollTop + input.offsetHeight + 'px';
- api.container.style.left = bounds.left + 'px';
- }
-
- function takeInput () {
- var value = input.value.trim();
- if (isEmpty()) {
- return;
- }
- var date = momentum.moment(value, o.inputFormat, o.strictParse);
- api.setValue(date);
- }
-
- function updateInput (data) {
- input.value = data;
- }
-
- function isEmpty () {
- return o.required === false && input.value.trim() === '';
- }
-
- function unrequire (fn) {
- return function maybe () {
- return isEmpty() ? null : fn.apply(this, arguments);
- };
- }
-}
-
-module.exports = inputCalendar;
-
-},{"./calendar":7,"./classes":8,"./clone":9,"./defaults":11,"./events":13,"./momentum":18,"./throttle":33,"raf":4}],17:[function(_dereq_,module,exports){
-'use strict';
-
-function isInput (elem) {
- return elem && elem.nodeName && elem.nodeName.toLowerCase() === 'input';
-}
-
-module.exports = isInput;
-
-},{}],18:[function(_dereq_,module,exports){
-'use strict';
-
-function isMoment (value) {
- return value && Object.prototype.hasOwnProperty.call(value, '_isAMomentObject');
-}
-
-var api = {
- moment: null,
- isMoment: isMoment
-};
-
-module.exports = api;
-
-},{}],19:[function(_dereq_,module,exports){
-'use strict';
-
-function noop () {}
-
-module.exports = noop;
-
-},{}],20:[function(_dereq_,module,exports){
-'use strict';
-
-var momentum = _dereq_('./momentum');
-
-function raw (date, format) {
- if (typeof date === 'string') {
- return momentum.moment(date, format);
- }
- if (Object.prototype.toString.call(date) === '[object Date]') {
- return momentum.moment(date);
- }
- if (momentum.isMoment(date)) {
- return date.clone();
- }
-}
-
-function parse (date, format) {
- var m = raw(date, typeof format === 'string' ? format : null);
- return m && m.isValid() ? m : null;
-}
-
-module.exports = parse;
-
-},{"./momentum":18}],21:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Array.prototype.filter) {
- Array.prototype.filter = function (fn, ctx) {
- var f = [];
- this.forEach(function (v, i, t) {
- if (fn.call(ctx, v, i, t)) { f.push(v); }
- }, ctx);
- return f;
- };
-}
-
-},{}],22:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Array.prototype.forEach) {
- Array.prototype.forEach = function (fn, ctx) {
- if (this === void 0 || this === null || typeof fn !== 'function') {
- throw new TypeError();
- }
- var t = this;
- var len = t.length;
- for (var i = 0; i < len; i++) {
- if (i in t) { fn.call(ctx, t[i], i, t); }
- }
- };
-}
-
-},{}],23:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (what, start) {
- if (this === undefined || this === null) {
- throw new TypeError();
- }
- var length = this.length;
- start = +start || 0;
- if (Math.abs(start) === Infinity) {
- start = 0;
- } else if (start < 0) {
- start += length;
- if (start < 0) { start = 0; }
- }
- for (; start < length; start++) {
- if (this[start] === what) {
- return start;
- }
- }
- return -1;
- };
-}
-
-},{}],24:[function(_dereq_,module,exports){
-'use strict';
-
-Array.isArray || (Array.isArray = function (a) {
- return '' + a !== a && Object.prototype.toString.call(a) === '[object Array]';
-});
-
-},{}],25:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Array.prototype.map) {
- Array.prototype.map = function (fn, ctx) {
- var context, result, i;
-
- if (this == null) {
- throw new TypeError('this is null or not defined');
- }
-
- var source = Object(this);
- var len = source.length >>> 0;
-
- if (typeof fn !== 'function') {
- throw new TypeError(fn + ' is not a function');
- }
-
- if (arguments.length > 1) {
- context = ctx;
- }
-
- result = new Array(len);
- i = 0;
-
- while (i < len) {
- if (i in source) {
- result[i] = fn.call(context, source[i], i, source);
- }
- i++;
- }
- return result;
- };
-}
-
-},{}],26:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Array.prototype.some) {
- Array.prototype.some = function (fn, ctx) {
- var context, i;
-
- if (this == null) {
- throw new TypeError('this is null or not defined');
- }
-
- var source = Object(this);
- var len = source.length >>> 0;
-
- if (typeof fn !== 'function') {
- throw new TypeError(fn + ' is not a function');
- }
-
- if (arguments.length > 1) {
- context = ctx;
- }
-
- i = 0;
-
- while (i < len) {
- if (i in source) {
- var test = fn.call(context, source[i], i, source);
- if (test) {
- return true;
- }
- }
- i++;
- }
- return false;
- };
-}
-
-},{}],27:[function(_dereq_,module,exports){
-'use strict';
-
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (context) {
- if (typeof this !== 'function') {
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var curried = Array.prototype.slice.call(arguments, 1);
- var original = this;
- var NoOp = function () {};
- var bound = function () {
- var ctx = this instanceof NoOp && context ? this : context;
- var args = curried.concat(Array.prototype.slice.call(arguments));
- return original.apply(ctx, args);
- };
- NoOp.prototype = this.prototype;
- bound.prototype = new NoOp();
- return bound;
- };
-}
-
-},{}],28:[function(_dereq_,module,exports){
-'use strict';
-
-var hasOwn = Object.prototype.hasOwnProperty;
-var hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString');
-var dontEnums = [
- 'toString',
- 'toLocaleString',
- 'valueOf',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'constructor'
-];
-var dontEnumsLength = dontEnums.length;
-
-if (!Object.keys) {
- Object.keys = function(obj) {
- if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
- throw new TypeError('Object.keys called on non-object');
- }
-
- var result = [], prop, i;
-
- for (prop in obj) {
- if (hasOwn.call(obj, prop)) {
- result.push(prop);
- }
- }
-
- if (hasDontEnumBug) {
- for (i = 0; i < dontEnumsLength; i++) {
- if (hasOwn.call(obj, dontEnums[i])) {
- result.push(dontEnums[i]);
- }
- }
- }
- return result;
- };
-}
-
-},{}],29:[function(_dereq_,module,exports){
-'use strict';
-
-if (!String.prototype.trim) {
- String.prototype.trim = function () {
- return this.replace(/^\s+|\s+$/g, '');
- };
-}
-
-},{}],30:[function(_dereq_,module,exports){
-'use strict';
-
-// these are only required for IE < 9
-// maybe move to IE-specific distro?
-_dereq_('./polyfills/function.bind');
-_dereq_('./polyfills/array.foreach');
-_dereq_('./polyfills/array.map');
-_dereq_('./polyfills/array.filter');
-_dereq_('./polyfills/array.isarray');
-_dereq_('./polyfills/array.indexof');
-_dereq_('./polyfills/array.some');
-_dereq_('./polyfills/string.trim');
-_dereq_('./polyfills/object.keys');
-
-var core = _dereq_('./core');
-var index = _dereq_('./index');
-var use = _dereq_('./use');
-
-core.use = use.bind(core);
-core.find = index.find;
-core.val = _dereq_('./validators');
-
-module.exports = core;
-
-},{"./core":10,"./index":14,"./polyfills/array.filter":21,"./polyfills/array.foreach":22,"./polyfills/array.indexof":23,"./polyfills/array.isarray":24,"./polyfills/array.map":25,"./polyfills/array.some":26,"./polyfills/function.bind":27,"./polyfills/object.keys":28,"./polyfills/string.trim":29,"./use":34,"./validators":35}],31:[function(_dereq_,module,exports){
-(function (global){
-var rome = _dereq_('./rome');
-var momentum = _dereq_('./momentum');
-
-rome.use(global.moment);
-
-if (momentum.moment === void 0) {
- throw new Error('rome depends on moment.js, you can get it at http://momentjs.com, or you could use the bundled distribution file instead.');
-}
-
-module.exports = rome;
-
-}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./momentum":18,"./rome":30}],32:[function(_dereq_,module,exports){
-'use strict';
-
-function text (elem, value) {
- if (arguments.length === 2) {
- elem.innerText = elem.textContent = value;
- }
- return elem.innerText || elem.textContent;
-}
-
-module.exports = text;
-
-},{}],33:[function(_dereq_,module,exports){
-'use strict';
-
-module.exports = function throttle (fn, boundary) {
- var last = -Infinity;
- var timer;
- return function bounced () {
- if (timer) {
- return;
- }
- unbound();
-
- function unbound () {
- clearTimeout(timer);
- timer = null;
- var next = last + boundary;
- var now = Date.now();
- if (now > next) {
- last = now;
- fn.apply(this, arguments);
- } else {
- timer = setTimeout(unbound, next - now);
- }
- }
- };
-};
-
-},{}],34:[function(_dereq_,module,exports){
-'use strict';
-
-var momentum = _dereq_('./momentum');
-
-function use (moment) {
- this.moment = momentum.moment = moment;
-}
-
-module.exports = use;
-
-},{"./momentum":18}],35:[function(_dereq_,module,exports){
-'use strict';
-
-var index = _dereq_('./index');
-var parse = _dereq_('./parse');
-var association = _dereq_('./association');
-
-function compareBuilder (compare) {
- return function factory (value) {
- var fixed = parse(value);
-
- return function validate (date) {
- var cal = index.find(value);
- var left = parse(date);
- var right = fixed || cal && cal.getMoment();
- if (!right) {
- return true;
- }
- if (cal) {
- association.add(this, cal);
- }
- return compare(left, right);
- };
- };
-}
-
-function rangeBuilder (how, compare) {
- return function factory (start, end) {
- var dates;
- var len = arguments.length;
-
- if (Array.isArray(start)) {
- dates = start;
- } else {
- if (len === 1) {
- dates = [start];
- } else if (len === 2) {
- dates = [[start, end]];
- }
- }
-
- return function validate (date) {
- return dates.map(expand.bind(this))[how](compare.bind(this, date));
- };
-
- function expand (value) {
- var start, end;
- var cal = index.find(value);
- if (cal) {
- start = end = cal.getMoment();
- } else if (Array.isArray(value)) {
- start = value[0]; end = value[1];
- } else {
- start = end = value;
- }
- if (cal) {
- association.add(cal, this);
- }
- return {
- start: parse(start).startOf('day').toDate(),
- end: parse(end).endOf('day').toDate()
- };
- }
- };
-}
-
-var afterEq = compareBuilder(function (left, right) { return left >= right; });
-var after = compareBuilder(function (left, right) { return left > right; });
-var beforeEq = compareBuilder(function (left, right) { return left <= right; });
-var before = compareBuilder(function (left, right) { return left < right; });
-
-var except = rangeBuilder('every', function (left, right) { return right.start > left || right.end < left; });
-var only = rangeBuilder('some', function (left, right) { return right.start <= left && right.end >= left; });
-
-module.exports = {
- afterEq: afterEq,
- after: after,
- beforeEq: beforeEq,
- before: before,
- except: except,
- only: only
-};
-
-},{"./association":6,"./index":14,"./parse":20}]},{},[31])
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaWNvL2Rldi9yb21lL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvbm9kZV9tb2R1bGVzL2NvbnRyYS5lbWl0dGVyL2luZGV4LmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvbm9kZV9tb2R1bGVzL2NvbnRyYS5lbWl0dGVyL3NyYy9jb250cmEuZW1pdHRlci5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL25vZGVfbW9kdWxlcy9yYWYvaW5kZXguanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9ub2RlX21vZHVsZXMvcmFmL25vZGVfbW9kdWxlcy9wZXJmb3JtYW5jZS1ub3cvbGliL3BlcmZvcm1hbmNlLW5vdy5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9hc3NvY2lhdGlvbi5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9jYWxlbmRhci5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9jbGFzc2VzLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL2Nsb25lLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL2NvcmUuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvZGVmYXVsdHMuanMiLCIvVXNlcnMvbmljby9kZXYvcm9
tZS9zcmMvZG9tLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL2V2ZW50cy5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9pbmRleC5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9pbmxpbmUuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvaW5wdXQuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvaXNJbnB1dC5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9tb21lbnR1bS5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9ub29wLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL3BhcnNlLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL3BvbHlmaWxscy9hcnJheS5maWx0ZXIuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvcG9seWZpbGxzL2FycmF5LmZvcmVhY2guanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvcG9seWZpbGxzL2FycmF5LmluZGV4b2YuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvcG9seWZpbGxzL2FycmF5LmlzYXJyYXkuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvcG9seWZpbGxzL2FycmF5Lm1hcC5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9wb2x5ZmlsbHMvYXJyYXkuc29tZS5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9wb2x5ZmlsbHMvZnVuY3Rpb24uYmluZC5qcyIsIi9Vc2Vycy9uaWNvL2Rldi9yb21lL3NyYy9wb2x5ZmlsbHMvb2JqZWN0LmtleXMuanMiLCIvVXNlcnMvbmljby9kZXYv
cm9tZS9zcmMvcG9seWZpbGxzL3N0cmluZy50cmltLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL3JvbWUuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvcm9tZS5zdGFuZGFsb25lLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL3RleHQuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvdGhyb3R0bGUuanMiLCIvVXNlcnMvbmljby9kZXYvcm9tZS9zcmMvdXNlLmpzIiwiL1VzZXJzL25pY28vZGV2L3JvbWUvc3JjL3ZhbGlkYXRvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Q
UFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQT
tBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUN
BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB
QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQ
TtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QU
FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0F
BQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD
QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ
UNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOz
tBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUN
BO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFD
QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvc
nRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBldi5zb3VyY2U7XG4gICAgICAgICAgIC
BpZiAoKHNvdXJjZSA9PT0gd2luZG93IHx8IHNvdXJjZSA9PT0gbnVsbCkgJiYgZXYuZGF0YSA9PT0gJ3Byb2Nlc3MtdGljaycpIHtcbiAgICAgICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAocXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZm4gPSBxdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBmbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgICAgICBxdWV1ZS5wdXNoKGZuKTtcbiAgICAgICAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgncHJvY2Vzcy10aWNrJywgJyonKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgc2V0VGltZW91dChmbiwgMCk7XG4gICAgfTtcbn0pKCk7XG5cbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDt
cbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vc3JjL2NvbnRyYS5lbWl0dGVyLmpzJyk7XG4iLCIoZnVuY3Rpb24gKHByb2Nlc3Mpe1xuKGZ1bmN0aW9uIChyb290LCB1bmRlZmluZWQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB1bmRlZiA9ICcnICsgdW5kZWZpbmVkO1xuICBmdW5jdGlvbiBhdG9hIChhLCBuKSB7IHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhLCBuKTsgfVxuICBmdW5jdGlvbiBkZWJvdW5jZSAoZm4sIGFyZ3MsIGN0eCkgeyBpZiAoIWZuKSB7IHJldHVybjsgfSB0aWNrKGZ1bmN0aW9uIHJ1biAoKSB7IGZuLmFwcGx5KGN0eCB8fCBudWxsLCBhcmdzIHx8IFtdKTsgfSk7IH1cblxuICAvLyBjcm9zcy1wbGF0Zm9ybSB0aWNrZXJcbiAgdmFyIHNpID0gdHlwZW9mIHNldEltbWVkaWF0ZSA9PT0gJ2Z1bmN0aW9u
JywgdGljaztcbiAgaWYgKHNpKSB7XG4gICAgdGljayA9IGZ1bmN0aW9uIChmbikgeyBzZXRJbW1lZGlhdGUoZm4pOyB9O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBwcm9jZXNzICE9PSB1bmRlZiAmJiBwcm9jZXNzLm5leHRUaWNrKSB7XG4gICAgdGljayA9IHByb2Nlc3MubmV4dFRpY2s7XG4gIH0gZWxzZSB7XG4gICAgdGljayA9IGZ1bmN0aW9uIChmbikgeyBzZXRUaW1lb3V0KGZuLCAwKTsgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9lbWl0dGVyICh0aGluZywgb3B0aW9ucykge1xuICAgIHZhciBvcHRzID0gb3B0aW9ucyB8fCB7fTtcbiAgICB2YXIgZXZ0ID0ge307XG4gICAgaWYgKHRoaW5nID09PSB1bmRlZmluZWQpIHsgdGhpbmcgPSB7fTsgfVxuICAgIHRoaW5nLm9uID0gZnVuY3Rpb24gKHR5cGUsIGZuKSB7XG4gICAgICBpZiAoIWV2dFt0eXBlXSkge1xuICAgICAgICBldnRbdHlwZV0gPSBbZm5dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXZ0W3R5cGVdLnB1c2goZm4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH07XG4gICAgdGhpbmcub25jZSA9IGZ1bmN0aW9uICh0eXBlLCBmbikge1xuICAgICAgZm4uX29uY2UgPSB0cnVlOyAvLyB0aGluZy5vZmYoZm4pIHN0aWxsIHdvcmtzIVxuICAgICAgdGhpbmcub24odHlwZSwgZm4pO1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH07XG4gICAgdGhpbmcub2ZmID0gZnVuY3Rpb24gKHR5cGUsIGZuKSB7XG4gICAgICB2YXIgYyA9IGFyZ
3VtZW50cy5sZW5ndGg7XG4gICAgICBpZiAoYyA9PT0gMSkge1xuICAgICAgICBkZWxldGUgZXZ0W3R5cGVdO1xuICAgICAgfSBlbHNlIGlmIChjID09PSAwKSB7XG4gICAgICAgIGV2dCA9IHt9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGV0ID0gZXZ0W3R5cGVdO1xuICAgICAgICBpZiAoIWV0KSB7IHJldHVybiB0aGluZzsgfVxuICAgICAgICBldC5zcGxpY2UoZXQuaW5kZXhPZihmbiksIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH07XG4gICAgdGhpbmcuZW1pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBhcmdzID0gYXRvYShhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIHRoaW5nLmVtaXR0ZXJTbmFwc2hvdChhcmdzLnNoaWZ0KCkpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH07XG4gICAgdGhpbmcuZW1pdHRlclNuYXBzaG90ID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgIHZhciBldCA9IChldnRbdHlwZV0gfHwgW10pLnNsaWNlKDApO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhdG9hKGFyZ3VtZW50cyk7XG4gICAgICAgIHZhciBjdHggPSB0aGlzIHx8IHRoaW5nO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ2Vycm9yJyAmJiBvcHRzLnRocm93cyAhPT0gZmFsc2UgJiYgIWV0Lmxlbmd0aCkgeyB0aHJvdyBhcmdzLmxlbmd0aCA9PT0gMSA/IGFyZ3NbMF0gOiBhcmdzOyB9XG4gICAgICAgIGV2dFt0eXBlXSA9IGV0LmZpbH
RlcihmdW5jdGlvbiBlbWl0dGVyIChsaXN0ZW4pIHtcbiAgICAgICAgICBpZiAob3B0cy5hc3luYykgeyBkZWJvdW5jZShsaXN0ZW4sIGFyZ3MsIGN0eCk7IH0gZWxzZSB7IGxpc3Rlbi5hcHBseShjdHgsIGFyZ3MpOyB9XG4gICAgICAgICAgcmV0dXJuICFsaXN0ZW4uX29uY2U7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpbmc7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpbmc7XG4gIH1cblxuICAvLyBjcm9zcy1wbGF0Zm9ybSBleHBvcnRcbiAgaWYgKHR5cGVvZiBtb2R1bGUgIT09IHVuZGVmICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBfZW1pdHRlcjtcbiAgfSBlbHNlIHtcbiAgICByb290LmNvbnRyYSA9IHJvb3QuY29udHJhIHx8IHt9O1xuICAgIHJvb3QuY29udHJhLmVtaXR0ZXIgPSBfZW1pdHRlcjtcbiAgfVxufSkodGhpcyk7XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiRldhQVNIXCIpKSIsInZhciBub3cgPSByZXF1aXJlKCdwZXJmb3JtYW5jZS1ub3cnKVxuICAsIGdsb2JhbCA9IHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnID8ge30gOiB3aW5kb3dcbiAgLCB2ZW5kb3JzID0gWydtb3onLCAnd2Via2l0J11cbiAgLCBzdWZmaXggPSAnQW5pbWF0aW9uRnJhbWUnXG4gICwgcmFmID0gZ2xvYmFsWydyZXF1ZXN0JyArIHN1ZmZpeF1cbiAgLCBjYWYgPSBnbG9iYWxbJ2NhbmNlbCcgKyBzdWZmaXhdIHx8IGdsb2JhbFsnY2FuY2VsUmVxdWV
zdCcgKyBzdWZmaXhdXG4gICwgaXNOYXRpdmUgPSB0cnVlXG5cbmZvcih2YXIgaSA9IDA7IGkgPCB2ZW5kb3JzLmxlbmd0aCAmJiAhcmFmOyBpKyspIHtcbiAgcmFmID0gZ2xvYmFsW3ZlbmRvcnNbaV0gKyAnUmVxdWVzdCcgKyBzdWZmaXhdXG4gIGNhZiA9IGdsb2JhbFt2ZW5kb3JzW2ldICsgJ0NhbmNlbCcgKyBzdWZmaXhdXG4gICAgICB8fCBnbG9iYWxbdmVuZG9yc1tpXSArICdDYW5jZWxSZXF1ZXN0JyArIHN1ZmZpeF1cbn1cblxuLy8gU29tZSB2ZXJzaW9ucyBvZiBGRiBoYXZlIHJBRiBidXQgbm90IGNBRlxuaWYoIXJhZiB8fCAhY2FmKSB7XG4gIGlzTmF0aXZlID0gZmFsc2VcblxuICB2YXIgbGFzdCA9IDBcbiAgICAsIGlkID0gMFxuICAgICwgcXVldWUgPSBbXVxuICAgICwgZnJhbWVEdXJhdGlvbiA9IDEwMDAgLyA2MFxuXG4gIHJhZiA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYocXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICB2YXIgX25vdyA9IG5vdygpXG4gICAgICAgICwgbmV4dCA9IE1hdGgubWF4KDAsIGZyYW1lRHVyYXRpb24gLSAoX25vdyAtIGxhc3QpKVxuICAgICAgbGFzdCA9IG5leHQgKyBfbm93XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY3AgPSBxdWV1ZS5zbGljZSgwKVxuICAgICAgICAvLyBDbGVhciBxdWV1ZSBoZXJlIHRvIHByZXZlbnRcbiAgICAgICAgLy8gY2FsbGJhY2tzIGZyb20gYXBwZW5kaW5nIGxpc3RlbmVyc1xuICAgICAgICAv
LyB0byB0aGUgY3VycmVudCBmcmFtZSdzIHF1ZXVlXG4gICAgICAgIHF1ZXVlLmxlbmd0aCA9IDBcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYoIWNwW2ldLmNhbmNlbGxlZCkge1xuICAgICAgICAgICAgdHJ5e1xuICAgICAgICAgICAgICBjcFtpXS5jYWxsYmFjayhsYXN0KVxuICAgICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IHRocm93IGUgfSwgMClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIE1hdGgucm91bmQobmV4dCkpXG4gICAgfVxuICAgIHF1ZXVlLnB1c2goe1xuICAgICAgaGFuZGxlOiArK2lkLFxuICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgY2FuY2VsbGVkOiBmYWxzZVxuICAgIH0pXG4gICAgcmV0dXJuIGlkXG4gIH1cblxuICBjYWYgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcXVldWUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmKHF1ZXVlW2ldLmhhbmRsZSA9PT0gaGFuZGxlKSB7XG4gICAgICAgIHF1ZXVlW2ldLmNhbmNlbGxlZCA9IHRydWVcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbikge1xuICAvLyBXcmFwIGluIGEgbmV3IGZ1bmN0aW9uIHRvIHByZXZlbnRcbiAgLy8gYGNhbmNlbGAgcG90ZW50aWFsbHkgYmVpbmcgYXNza
WduZWRcbiAgLy8gdG8gdGhlIG5hdGl2ZSByQUYgZnVuY3Rpb25cbiAgaWYoIWlzTmF0aXZlKSB7XG4gICAgcmV0dXJuIHJhZi5jYWxsKGdsb2JhbCwgZm4pXG4gIH1cbiAgcmV0dXJuIHJhZi5jYWxsKGdsb2JhbCwgZnVuY3Rpb24oKSB7XG4gICAgdHJ5e1xuICAgICAgZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKVxuICAgIH0gY2F0Y2goZSkge1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgdGhyb3cgZSB9LCAwKVxuICAgIH1cbiAgfSlcbn1cbm1vZHVsZS5leHBvcnRzLmNhbmNlbCA9IGZ1bmN0aW9uKCkge1xuICBjYWYuYXBwbHkoZ2xvYmFsLCBhcmd1bWVudHMpXG59XG4iLCIoZnVuY3Rpb24gKHByb2Nlc3Mpe1xuLy8gR2VuZXJhdGVkIGJ5IENvZmZlZVNjcmlwdCAxLjYuM1xuKGZ1bmN0aW9uKCkge1xuICB2YXIgZ2V0TmFub1NlY29uZHMsIGhydGltZSwgbG9hZFRpbWU7XG5cbiAgaWYgKCh0eXBlb2YgcGVyZm9ybWFuY2UgIT09IFwidW5kZWZpbmVkXCIgJiYgcGVyZm9ybWFuY2UgIT09IG51bGwpICYmIHBlcmZvcm1hbmNlLm5vdykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgfTtcbiAgfSBlbHNlIGlmICgodHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2VzcyAhPT0gbnVsbCkgJiYgcHJvY2Vzcy5ocnRpbWUpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgIC
AgcmV0dXJuIChnZXROYW5vU2Vjb25kcygpIC0gbG9hZFRpbWUpIC8gMWU2O1xuICAgIH07XG4gICAgaHJ0aW1lID0gcHJvY2Vzcy5ocnRpbWU7XG4gICAgZ2V0TmFub1NlY29uZHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBocjtcbiAgICAgIGhyID0gaHJ0aW1lKCk7XG4gICAgICByZXR1cm4gaHJbMF0gKiAxZTkgKyBoclsxXTtcbiAgICB9O1xuICAgIGxvYWRUaW1lID0gZ2V0TmFub1NlY29uZHMoKTtcbiAgfSBlbHNlIGlmIChEYXRlLm5vdykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gRGF0ZS5ub3coKSAtIGxvYWRUaW1lO1xuICAgIH07XG4gICAgbG9hZFRpbWUgPSBEYXRlLm5vdygpO1xuICB9IGVsc2Uge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSBsb2FkVGltZTtcbiAgICB9O1xuICAgIGxvYWRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gIH1cblxufSkuY2FsbCh0aGlzKTtcblxuLypcbi8vQCBzb3VyY2VNYXBwaW5nVVJMPXBlcmZvcm1hbmNlLW5vdy5tYXBcbiovXG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiRldhQVNIXCIpKSIsIid1c2Ugc3RyaWN0JztcblxudmFyIGlzSW5wdXQgPSByZXF1aXJlKCcuL2lzSW5wdXQnKTtcbnZhciBiaW5kaW5ncyA9IHt9O1xuXG5mdW5jdGlvbiBoYXMgKHNvdXJjZSwgdGFyZ2V0KSB7XG4gIHZhciBiaW5kaW5nID0gYml
uZGluZ3Nbc291cmNlLmlkXTtcbiAgcmV0dXJuIGJpbmRpbmcgJiYgYmluZGluZ1t0YXJnZXQuaWRdO1xufVxuXG5mdW5jdGlvbiBpbnNlcnQgKHNvdXJjZSwgdGFyZ2V0KSB7XG4gIHZhciBiaW5kaW5nID0gYmluZGluZ3Nbc291cmNlLmlkXTtcbiAgaWYgKCFiaW5kaW5nKSB7XG4gICAgYmluZGluZyA9IGJpbmRpbmdzW3NvdXJjZS5pZF0gPSB7fTtcbiAgfVxuICB2YXIgaW52YWxpZGF0ZSA9IGludmFsaWRhdG9yKHRhcmdldCk7XG4gIGJpbmRpbmdbdGFyZ2V0LmlkXSA9IGludmFsaWRhdGU7XG4gIHNvdXJjZS5vbignZGF0YScsIGludmFsaWRhdGUpO1xuICBzb3VyY2Uub24oJ2Rlc3Ryb3llZCcsIHJlbW92ZS5iaW5kKG51bGwsIHNvdXJjZSwgdGFyZ2V0KSk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSAoc291cmNlLCB0YXJnZXQpIHtcbiAgdmFyIGJpbmRpbmcgPSBiaW5kaW5nc1tzb3VyY2UuaWRdO1xuICBpZiAoIWJpbmRpbmcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGludmFsaWRhdGUgPSBiaW5kaW5nW3RhcmdldC5pZF07XG4gIHNvdXJjZS5vZmYoJ2RhdGEnLCBpbnZhbGlkYXRlKTtcbiAgZGVsZXRlIGJpbmRpbmdbdGFyZ2V0LmlkXTtcbn1cblxuZnVuY3Rpb24gaW52YWxpZGF0b3IgKHRhcmdldCkge1xuICByZXR1cm4gZnVuY3Rpb24gaW52YWxpZGF0ZSAoKSB7XG4gICAgdGFyZ2V0LnJlZnJlc2goKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYWRkIChzb3VyY2UsIHRhcmdldCkge1xuICBpZiAoaXNJ
bnB1dCh0YXJnZXQuYXNzb2NpYXRlZCkgfHwgaGFzKHNvdXJjZSwgdGFyZ2V0KSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpbnNlcnQoc291cmNlLCB0YXJnZXQpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgYWRkOiBhZGQsXG4gIHJlbW92ZTogcmVtb3ZlXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZW1pdHRlciA9IHJlcXVpcmUoJ2NvbnRyYS5lbWl0dGVyJyk7XG52YXIgcmFmID0gcmVxdWlyZSgncmFmJyk7XG52YXIgZG9tID0gcmVxdWlyZSgnLi9kb20nKTtcbnZhciB0ZXh0ID0gcmVxdWlyZSgnLi90ZXh0Jyk7XG52YXIgcGFyc2UgPSByZXF1aXJlKCcuL3BhcnNlJyk7XG52YXIgY2xvbmUgPSByZXF1aXJlKCcuL2Nsb25lJyk7XG52YXIgZGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG52YXIgbW9tZW50dW0gPSByZXF1aXJlKCcuL21vbWVudHVtJyk7XG52YXIgY2xhc3NlcyA9IHJlcXVpcmUoJy4vY2xhc3NlcycpO1xudmFyIGV2ZW50cyA9IHJlcXVpcmUoJy4vZXZlbnRzJyk7XG52YXIgbm9vcCA9IHJlcXVpcmUoJy4vbm9vcCcpO1xudmFyIG5vO1xuXG5mdW5jdGlvbiBjYWxlbmRhciAoY2FsZW5kYXJPcHRpb25zKSB7XG4gIHZhciBvO1xuICB2YXIgYXBpID0gZW1pdHRlcih7fSk7XG4gIHZhciByZWY7XG4gIHZhciByZWZDYWw7XG4gIHZhciBjb250YWluZXI7XG4gIHZhciByZW5kZXJlZCA9IGZhbHNlO1xuXG4gIC8vIGRhdGUgdmFyaWFibGVzXG4gIHZhciBtb250aE9mZnNld
EF0dHJpYnV0ZSA9ICdkYXRhLXJvbWUtb2Zmc2V0JztcbiAgdmFyIHdlZWtkYXlzO1xuICB2YXIgd2Vla2RheUNvdW50O1xuICB2YXIgY2FsZW5kYXJNb250aHMgPSBbXTtcbiAgdmFyIGxhc3RZZWFyO1xuICB2YXIgbGFzdE1vbnRoO1xuICB2YXIgbGFzdERheTtcbiAgdmFyIGxhc3REYXlFbGVtZW50O1xuICB2YXIgZGF0ZXdyYXBwZXI7XG4gIHZhciBiYWNrO1xuICB2YXIgbmV4dDtcblxuICAvLyB0aW1lIHZhcmlhYmxlc1xuICB2YXIgc2Vjb25kc0luRGF5ID0gNjAgKiA2MCAqIDI0O1xuICB2YXIgdGltZTtcbiAgdmFyIHRpbWVsaXN0O1xuXG4gIGluaXQoKTtcbiAgcmFmKHJlYWR5KTtcblxuICByZXR1cm4gYXBpO1xuXG4gIGZ1bmN0aW9uIG5hcGkgKCkgeyByZXR1cm4gYXBpOyB9XG5cbiAgZnVuY3Rpb24gaW5pdCAoaW5pdE9wdGlvbnMpIHtcbiAgICBvID0gZGVmYXVsdHMoaW5pdE9wdGlvbnMgfHwgY2FsZW5kYXJPcHRpb25zLCBhcGkpO1xuICAgIGlmICghY29udGFpbmVyKSB7IGNvbnRhaW5lciA9IGRvbSh7IGNsYXNzTmFtZTogby5zdHlsZXMuY29udGFpbmVyIH0pOyB9XG4gICAgd2Vla2RheXMgPSBvLndlZWtkYXlGb3JtYXQ7XG4gICAgd2Vla2RheUNvdW50ID0gd2Vla2RheXMubGVuZ3RoO1xuICAgIGxhc3RNb250aCA9IG5vO1xuICAgIGxhc3RZZWFyID0gbm87XG4gICAgbGFzdERheSA9IG5vO1xuICAgIGxhc3REYXlFbGVtZW50ID0gbm87XG4gICAgby5hcHBlbmRUby5hcHBlbmRDaGlsZChjb250YW
luZXIpO1xuXG4gICAgcmVtb3ZlQ2hpbGRyZW4oY29udGFpbmVyKTtcbiAgICByZW5kZXJlZCA9IGZhbHNlO1xuICAgIHJlZiA9IG8uaW5pdGlhbFZhbHVlID8gby5pbml0aWFsVmFsdWUgOiBtb21lbnR1bS5tb21lbnQoKTtcbiAgICByZWZDYWwgPSByZWYuY2xvbmUoKTtcblxuICAgIGFwaS5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgYXBpLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgIGFwaS5kZXN0cm95ID0gZGVzdHJveS5iaW5kKGFwaSwgZmFsc2UpO1xuICAgIGFwaS5lbWl0VmFsdWVzID0gZW1pdFZhbHVlcztcbiAgICBhcGkuZ2V0RGF0ZSA9IGdldERhdGU7XG4gICAgYXBpLmdldERhdGVTdHJpbmcgPSBnZXREYXRlU3RyaW5nO1xuICAgIGFwaS5nZXRNb21lbnQgPSBnZXRNb21lbnQ7XG4gICAgYXBpLmhpZGUgPSBoaWRlO1xuICAgIGFwaS5vcHRpb25zID0gY2hhbmdlT3B0aW9ucztcbiAgICBhcGkub3B0aW9ucy5yZXNldCA9IHJlc2V0T3B0aW9ucztcbiAgICBhcGkucmVmcmVzaCA9IHJlZnJlc2g7XG4gICAgYXBpLnJlc3RvcmUgPSBuYXBpO1xuICAgIGFwaS5zZXRWYWx1ZSA9IHNldFZhbHVlO1xuICAgIGFwaS5zaG93ID0gc2hvdztcblxuICAgIHNob3coKTtcbiAgICBldmVudExpc3RlbmluZygpO1xuICAgIHJlYWR5KCk7XG5cbiAgICByZXR1cm4gYXBpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVhZHkgKCkge1xuICAgIGFwaS5lbWl0KCdyZWFkeScsIGNsb25lKG8pKTtcbiAgfVxuXG4gIGZ1bmN0aW9
uIGRlc3Ryb3kgKHNpbGVudCkge1xuICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgIGNvbnRhaW5lci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGNvbnRhaW5lcik7XG4gICAgfVxuXG4gICAgaWYgKG8pIHtcbiAgICAgIGV2ZW50TGlzdGVuaW5nKHRydWUpO1xuICAgIH1cblxuICAgIHZhciBkZXN0cm95ZWQgPSBhcGkuZW1pdHRlclNuYXBzaG90KCdkZXN0cm95ZWQnKTtcbiAgICBhcGkuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICBhcGkuZGVzdHJveSA9IG5hcGk7XG4gICAgYXBpLmVtaXRWYWx1ZXMgPSBuYXBpO1xuICAgIGFwaS5nZXREYXRlID0gbm9vcDtcbiAgICBhcGkuZ2V0RGF0ZVN0cmluZyA9IG5vb3A7XG4gICAgYXBpLmdldE1vbWVudCA9IG5vb3A7XG4gICAgYXBpLmhpZGUgPSBuYXBpO1xuICAgIGFwaS5vcHRpb25zID0gbmFwaTtcbiAgICBhcGkub3B0aW9ucy5yZXNldCA9IG5hcGk7XG4gICAgYXBpLnJlZnJlc2ggPSBuYXBpO1xuICAgIGFwaS5yZXN0b3JlID0gaW5pdDtcbiAgICBhcGkuc2V0VmFsdWUgPSBuYXBpO1xuICAgIGFwaS5zaG93ID0gbmFwaTtcbiAgICBhcGkub2ZmKCk7XG5cbiAgICBpZiAoc2lsZW50ICE9PSB0cnVlKSB7XG4gICAgICBkZXN0cm95ZWQoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpO1xuICB9XG5cbiAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5pbmcgKHJlbW92ZSkge1xuICAgIHZhciBvcCA9IHJlbW92ZSA/ICdyZW1vdmUnIDogJ2FkZCc7XG4gICAgaWYgKG8uYXV0b0hpZGVP
bkJsdXIpIHsgZXZlbnRzW29wXShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICdmb2N1cycsIGhpZGVPbkJsdXIsIHRydWUpOyB9XG4gICAgaWYgKG8uYXV0b0hpZGVPbkNsaWNrKSB7IGV2ZW50c1tvcF0oZG9jdW1lbnQsICdjbGljaycsIGhpZGVPbkNsaWNrKTsgfVxuICB9XG5cbiAgZnVuY3Rpb24gY2hhbmdlT3B0aW9ucyAob3B0aW9ucykge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gY2xvbmUobyk7XG4gICAgfVxuICAgIGRlc3Ryb3koKTtcbiAgICBpbml0KG9wdGlvbnMpO1xuICAgIHJldHVybiBhcGk7XG4gIH1cblxuICBmdW5jdGlvbiByZXNldE9wdGlvbnMgKCkge1xuICAgIHJldHVybiBjaGFuZ2VPcHRpb25zKHsgYXBwZW5kVG86IG8uYXBwZW5kVG8gfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZW5kZXIgKCkge1xuICAgIGlmIChyZW5kZXJlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICByZW5kZXJlZCA9IHRydWU7XG4gICAgcmVuZGVyRGF0ZXMoKTtcbiAgICByZW5kZXJUaW1lKCk7XG4gICAgYXBpLmVtaXQoJ3JlbmRlcicpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVuZGVyRGF0ZXMgKCkge1xuICAgIGlmICghby5kYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBpO1xuICAgIGNhbGVuZGFyTW9udGhzID0gW107XG5cbiAgICBkYXRld3JhcHBlciA9IGRvbSh7IGNsYXNzTmFtZTogby5zdHlsZXMuZGF0ZSwgcGFyZW50OiBjb250Y
WluZXIgfSk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgby5tb250aHNJbkNhbGVuZGFyOyBpKyspIHtcbiAgICAgIHJlbmRlck1vbnRoKGkpO1xuICAgIH1cblxuICAgIGV2ZW50cy5hZGQoYmFjaywgJ2NsaWNrJywgc3VidHJhY3RNb250aCk7XG4gICAgZXZlbnRzLmFkZChuZXh0LCAnY2xpY2snLCBhZGRNb250aCk7XG4gICAgZXZlbnRzLmFkZChkYXRld3JhcHBlciwgJ2NsaWNrJywgcGlja0RheSk7XG5cbiAgICBmdW5jdGlvbiByZW5kZXJNb250aCAoaSkge1xuICAgICAgdmFyIG1vbnRoID0gZG9tKHsgY2xhc3NOYW1lOiBvLnN0eWxlcy5tb250aCwgcGFyZW50OiBkYXRld3JhcHBlciB9KTtcbiAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgIGJhY2sgPSBkb20oeyB0eXBlOiAnYnV0dG9uJywgY2xhc3NOYW1lOiBvLnN0eWxlcy5iYWNrLCBhdHRyaWJ1dGVzOiB7IHR5cGU6ICdidXR0b24nIH0sIHBhcmVudDogbW9udGggfSk7XG4gICAgICB9XG4gICAgICBpZiAoaSA9PT0gby5tb250aHNJbkNhbGVuZGFyIC0xKSB7XG4gICAgICAgIG5leHQgPSBkb20oeyB0eXBlOiAnYnV0dG9uJywgY2xhc3NOYW1lOiBvLnN0eWxlcy5uZXh0LCBhdHRyaWJ1dGVzOiB7IHR5cGU6ICdidXR0b24nIH0sIHBhcmVudDogbW9udGggfSk7XG4gICAgICB9XG4gICAgICB2YXIgbGFiZWwgPSBkb20oeyBjbGFzc05hbWU6IG8uc3R5bGVzLm1vbnRoTGFiZWwsIHBhcmVudDogbW9udGggfSk7XG4gICAgICB2YXIgZGF0ZSA9IGRvbSh7IH
R5cGU6ICd0YWJsZScsIGNsYXNzTmFtZTogby5zdHlsZXMuZGF5VGFibGUsIHBhcmVudDogbW9udGggfSk7XG4gICAgICB2YXIgZGF0ZWhlYWQgPSBkb20oeyB0eXBlOiAndGhlYWQnLCBjbGFzc05hbWU6IG8uc3R5bGVzLmRheUhlYWQsIHBhcmVudDogZGF0ZSB9KTtcbiAgICAgIHZhciBkYXRlaGVhZHJvdyA9IGRvbSh7IHR5cGU6ICd0cicsIGNsYXNzTmFtZTogby5zdHlsZXMuZGF5Um93LCBwYXJlbnQ6IGRhdGVoZWFkIH0pO1xuICAgICAgdmFyIGRhdGVib2R5ID0gZG9tKHsgdHlwZTogJ3Rib2R5JywgY2xhc3NOYW1lOiBvLnN0eWxlcy5kYXlCb2R5LCBwYXJlbnQ6IGRhdGUgfSk7XG4gICAgICB2YXIgajtcblxuICAgICAgZm9yIChqID0gMDsgaiA8IHdlZWtkYXlDb3VudDsgaisrKSB7XG4gICAgICAgIGRvbSh7IHR5cGU6ICd0aCcsIGNsYXNzTmFtZTogby5zdHlsZXMuZGF5SGVhZEVsZW0sIHBhcmVudDogZGF0ZWhlYWRyb3csIHRleHQ6IHdlZWtkYXlzW3dlZWtkYXkoaildIH0pO1xuICAgICAgfVxuXG4gICAgICBkYXRlYm9keS5zZXRBdHRyaWJ1dGUobW9udGhPZmZzZXRBdHRyaWJ1dGUsIGkpO1xuICAgICAgY2FsZW5kYXJNb250aHMucHVzaCh7XG4gICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgYm9keTogZGF0ZWJvZHlcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbmRlclRpbWUgKCkge1xuICAgIGlmICghby50aW1lIHx8ICFvLnRpbWVJbnRlcnZhbCkge1xuICAgICAgcmV
0dXJuO1xuICAgIH1cbiAgICB2YXIgdGltZXdyYXBwZXIgPSBkb20oeyBjbGFzc05hbWU6IG8uc3R5bGVzLnRpbWUsIHBhcmVudDogY29udGFpbmVyIH0pO1xuICAgIHRpbWUgPSBkb20oeyBjbGFzc05hbWU6IG8uc3R5bGVzLnNlbGVjdGVkVGltZSwgcGFyZW50OiB0aW1ld3JhcHBlciwgdGV4dDogcmVmLmZvcm1hdChvLnRpbWVGb3JtYXQpIH0pO1xuICAgIGV2ZW50cy5hZGQodGltZSwgJ2NsaWNrJywgdG9nZ2xlVGltZUxpc3QpO1xuICAgIHRpbWVsaXN0ID0gZG9tKHsgY2xhc3NOYW1lOiBvLnN0eWxlcy50aW1lTGlzdCwgcGFyZW50OiB0aW1ld3JhcHBlciB9KTtcbiAgICBldmVudHMuYWRkKHRpbWVsaXN0LCAnY2xpY2snLCBwaWNrVGltZSk7XG4gICAgdmFyIG5leHQgPSBtb21lbnR1bS5tb21lbnQoJzAwOjAwOjAwJywgJ0hIOm1tOnNzJyk7XG4gICAgdmFyIGxhdGVzdCA9IG5leHQuY2xvbmUoKS5hZGQoMSwgJ2RheXMnKTtcbiAgICB3aGlsZSAobmV4dC5pc0JlZm9yZShsYXRlc3QpKSB7XG4gICAgICBkb20oeyBjbGFzc05hbWU6IG8uc3R5bGVzLnRpbWVPcHRpb24sIHBhcmVudDogdGltZWxpc3QsIHRleHQ6IG5leHQuZm9ybWF0KG8udGltZUZvcm1hdCkgfSk7XG4gICAgICBuZXh0LmFkZChvLnRpbWVJbnRlcnZhbCwgJ3NlY29uZHMnKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB3ZWVrZGF5IChpbmRleCwgYmFja3dhcmRzKSB7XG4gICAgdmFyIGZhY3RvciA9IGJhY2t3YXJkcyA/IC0xIDogMTtcbiAg
ICB2YXIgb2Zmc2V0ID0gaW5kZXggKyBvLndlZWtTdGFydCAqIGZhY3RvcjtcbiAgICBpZiAob2Zmc2V0ID49IHdlZWtkYXlDb3VudCB8fCBvZmZzZXQgPCAwKSB7XG4gICAgICBvZmZzZXQgKz0gd2Vla2RheUNvdW50ICogLWZhY3RvcjtcbiAgICB9XG4gICAgcmV0dXJuIG9mZnNldDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRpc3BsYXlWYWxpZFRpbWVzT25seSAoKSB7XG4gICAgaWYgKCFvLnRpbWUgfHwgIXJlbmRlcmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lcyA9IHRpbWVsaXN0LmNoaWxkcmVuO1xuICAgIHZhciBsZW5ndGggPSB0aW1lcy5sZW5ndGg7XG4gICAgdmFyIGRhdGU7XG4gICAgdmFyIHRpbWU7XG4gICAgdmFyIGl0ZW07XG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpdGVtID0gdGltZXNbaV07XG4gICAgICB0aW1lID0gbW9tZW50dW0ubW9tZW50KHRleHQoaXRlbSksIG8udGltZUZvcm1hdCk7XG4gICAgICBkYXRlID0gc2V0VGltZShyZWYuY2xvbmUoKSwgdGltZSk7XG4gICAgICBpdGVtLnN0eWxlLmRpc3BsYXkgPSBpc0luUmFuZ2UoZGF0ZSwgZmFsc2UsIG8udGltZVZhbGlkYXRvcikgPyAnYmxvY2snIDogJ25vbmUnO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRvZ2dsZVRpbWVMaXN0IChzaG93KSB7XG4gICAgdmFyIGRpc3BsYXkgPSB0eXBlb2Ygc2hvdyA9PT0gJ2Jvb2xlYW4nID8gc2hvdyA6IHRpbWVsaXN0L
nN0eWxlLmRpc3BsYXkgPT09ICdub25lJztcbiAgICBpZiAoZGlzcGxheSkge1xuICAgICAgc2hvd1RpbWVMaXN0KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhpZGVUaW1lTGlzdCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3dUaW1lTGlzdCAoKSB7IGlmICh0aW1lbGlzdCkgeyB0aW1lbGlzdC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsgfSB9XG4gIGZ1bmN0aW9uIGhpZGVUaW1lTGlzdCAoKSB7IGlmICh0aW1lbGlzdCkgeyB0aW1lbGlzdC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOyB9IH1cbiAgZnVuY3Rpb24gc2hvd0NhbGVuZGFyICgpIHsgY29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSAnaW5saW5lLWJsb2NrJzsgYXBpLmVtaXQoJ3Nob3cnKTsgfVxuICBmdW5jdGlvbiBoaWRlQ2FsZW5kYXIgKCkgeyBjb250YWluZXIuc3R5bGUuZGlzcGxheSA9ICdub25lJzsgYXBpLmVtaXQoJ2hpZGUnKTsgfVxuXG4gIGZ1bmN0aW9uIHNob3cgKCkge1xuICAgIHJlbmRlcigpO1xuICAgIHJlZnJlc2goKTtcbiAgICB0b2dnbGVUaW1lTGlzdCghby5kYXRlKTtcbiAgICBzaG93Q2FsZW5kYXIoKTtcbiAgICByZXR1cm4gYXBpO1xuICB9XG5cbiAgZnVuY3Rpb24gaGlkZSAoKSB7XG4gICAgaGlkZVRpbWVMaXN0KCk7XG4gICAgcmFmKGhpZGVDYWxlbmRhcik7XG4gICAgcmV0dXJuIGFwaTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhpZGVDb25kaXRpb25hbGx5ICgpIHtcbiAgICBoaWRlVGltZUxpc3QoKTtcblxuICAgIH
ZhciBwb3MgPSBjbGFzc2VzLmNvbnRhaW5zKGNvbnRhaW5lciwgby5zdHlsZXMucG9zaXRpb25lZCk7XG4gICAgaWYgKHBvcykge1xuICAgICAgcmFmKGhpZGVDYWxlbmRhcik7XG4gICAgfVxuICAgIHJldHVybiBhcGk7XG4gIH1cblxuICBmdW5jdGlvbiBjYWxlbmRhckV2ZW50VGFyZ2V0IChlKSB7XG4gICAgdmFyIHRhcmdldCA9IGUudGFyZ2V0O1xuICAgIGlmICh0YXJnZXQgPT09IGFwaS5hc3NvY2lhdGVkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgd2hpbGUgKHRhcmdldCkge1xuICAgICAgaWYgKHRhcmdldCA9PT0gY29udGFpbmVyKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGlkZU9uQmx1ciAoZSkge1xuICAgIGlmIChjYWxlbmRhckV2ZW50VGFyZ2V0KGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGhpZGVDb25kaXRpb25hbGx5KCk7XG4gIH1cblxuICBmdW5jdGlvbiBoaWRlT25DbGljayAoZSkge1xuICAgIGlmIChjYWxlbmRhckV2ZW50VGFyZ2V0KGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGhpZGVDb25kaXRpb25hbGx5KCk7XG4gIH1cblxuICBmdW5jdGlvbiBzdWJ0cmFjdE1vbnRoICgpIHsgY2hhbmdlTW9udGgoJ3N1YnRyYWN0Jyk7IH1cbiAgZnVuY3Rpb24gYWRkTW9udGggKCkgeyBjaGFuZ2VNb250aCgnYWRkJyk7IH1cbiA
gZnVuY3Rpb24gY2hhbmdlTW9udGggKG9wKSB7XG4gICAgdmFyIGJvdW5kO1xuICAgIHZhciBkaXJlY3Rpb24gPSBvcCA9PT0gJ2FkZCcgPyAtMSA6IDE7XG4gICAgdmFyIG9mZnNldCA9IG8ubW9udGhzSW5DYWxlbmRhciArIGRpcmVjdGlvbiAqIGdldE1vbnRoT2Zmc2V0KGxhc3REYXlFbGVtZW50KTtcbiAgICByZWZDYWxbb3BdKG9mZnNldCwgJ21vbnRocycpO1xuICAgIGJvdW5kID0gaW5SYW5nZShyZWZDYWwuY2xvbmUoKSk7XG4gICAgcmVmID0gYm91bmQgfHwgcmVmO1xuICAgIGlmIChib3VuZCkgeyByZWZDYWwgPSBib3VuZC5jbG9uZSgpOyB9XG4gICAgdXBkYXRlKCk7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGUgKHNpbGVudCkge1xuICAgIHVwZGF0ZUNhbGVuZGFyKCk7XG4gICAgdXBkYXRlVGltZSgpO1xuICAgIGlmIChzaWxlbnQgIT09IHRydWUpIHsgZW1pdFZhbHVlcygpOyB9XG4gICAgZGlzcGxheVZhbGlkVGltZXNPbmx5KCk7XG4gIH1cblxuICBmdW5jdGlvbiB1cGRhdGVDYWxlbmRhciAoKSB7XG4gICAgaWYgKCFvLmRhdGUgfHwgIXJlbmRlcmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB5ID0gcmVmQ2FsLnllYXIoKTtcbiAgICB2YXIgbSA9IHJlZkNhbC5tb250aCgpO1xuICAgIHZhciBkID0gcmVmQ2FsLmRhdGUoKTtcbiAgICBpZiAoZCA9PT0gbGFzdERheSAmJiBtID09PSBsYXN0TW9udGggJiYgeSA9PT0gbGFzdFllYXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4g
ICAgdmFyIGNhblN0YXkgPSBpc0Rpc3BsYXllZCgpO1xuICAgIGxhc3REYXkgPSByZWZDYWwuZGF0ZSgpO1xuICAgIGxhc3RNb250aCA9IHJlZkNhbC5tb250aCgpO1xuICAgIGxhc3RZZWFyID0gcmVmQ2FsLnllYXIoKTtcbiAgICBpZiAoY2FuU3
<TRUNCATED>
[06/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/moment-2.10.3.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/moment-2.10.3.js b/htrace-htraced/src/web/lib/moment-2.10.3.js
new file mode 100644
index 0000000..275a3c3
--- /dev/null
+++ b/htrace-htraced/src/web/lib/moment-2.10.3.js
@@ -0,0 +1,3111 @@
+//! moment.js
+//! version : 2.10.3
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.moment = factory()
+}(this, function () { 'use strict';
+
+ var hookCallback;
+
+ function utils_hooks__hooks () {
+ return hookCallback.apply(null, arguments);
+ }
+
+ // This is done to register the method called with moment()
+ // without creating circular dependencies.
+ function setHookCallback (callback) {
+ hookCallback = callback;
+ }
+
+ function isArray(input) {
+ return Object.prototype.toString.call(input) === '[object Array]';
+ }
+
+ function isDate(input) {
+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
+ }
+
+ function map(arr, fn) {
+ var res = [], i;
+ for (i = 0; i < arr.length; ++i) {
+ res.push(fn(arr[i], i));
+ }
+ return res;
+ }
+
+ function hasOwnProp(a, b) {
+ return Object.prototype.hasOwnProperty.call(a, b);
+ }
+
+ function extend(a, b) {
+ for (var i in b) {
+ if (hasOwnProp(b, i)) {
+ a[i] = b[i];
+ }
+ }
+
+ if (hasOwnProp(b, 'toString')) {
+ a.toString = b.toString;
+ }
+
+ if (hasOwnProp(b, 'valueOf')) {
+ a.valueOf = b.valueOf;
+ }
+
+ return a;
+ }
+
+ function create_utc__createUTC (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
+ }
+
+ function defaultParsingFlags() {
+ // We need to deep clone this object.
+ return {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ invalidFormat : false,
+ userInvalidated : false,
+ iso : false
+ };
+ }
+
+ function getParsingFlags(m) {
+ if (m._pf == null) {
+ m._pf = defaultParsingFlags();
+ }
+ return m._pf;
+ }
+
+ function valid__isValid(m) {
+ if (m._isValid == null) {
+ var flags = getParsingFlags(m);
+ m._isValid = !isNaN(m._d.getTime()) &&
+ flags.overflow < 0 &&
+ !flags.empty &&
+ !flags.invalidMonth &&
+ !flags.nullInput &&
+ !flags.invalidFormat &&
+ !flags.userInvalidated;
+
+ if (m._strict) {
+ m._isValid = m._isValid &&
+ flags.charsLeftOver === 0 &&
+ flags.unusedTokens.length === 0 &&
+ flags.bigHour === undefined;
+ }
+ }
+ return m._isValid;
+ }
+
+ function valid__createInvalid (flags) {
+ var m = create_utc__createUTC(NaN);
+ if (flags != null) {
+ extend(getParsingFlags(m), flags);
+ }
+ else {
+ getParsingFlags(m).userInvalidated = true;
+ }
+
+ return m;
+ }
+
+ var momentProperties = utils_hooks__hooks.momentProperties = [];
+
+ function copyConfig(to, from) {
+ var i, prop, val;
+
+ if (typeof from._isAMomentObject !== 'undefined') {
+ to._isAMomentObject = from._isAMomentObject;
+ }
+ if (typeof from._i !== 'undefined') {
+ to._i = from._i;
+ }
+ if (typeof from._f !== 'undefined') {
+ to._f = from._f;
+ }
+ if (typeof from._l !== 'undefined') {
+ to._l = from._l;
+ }
+ if (typeof from._strict !== 'undefined') {
+ to._strict = from._strict;
+ }
+ if (typeof from._tzm !== 'undefined') {
+ to._tzm = from._tzm;
+ }
+ if (typeof from._isUTC !== 'undefined') {
+ to._isUTC = from._isUTC;
+ }
+ if (typeof from._offset !== 'undefined') {
+ to._offset = from._offset;
+ }
+ if (typeof from._pf !== 'undefined') {
+ to._pf = getParsingFlags(from);
+ }
+ if (typeof from._locale !== 'undefined') {
+ to._locale = from._locale;
+ }
+
+ if (momentProperties.length > 0) {
+ for (i in momentProperties) {
+ prop = momentProperties[i];
+ val = from[prop];
+ if (typeof val !== 'undefined') {
+ to[prop] = val;
+ }
+ }
+ }
+
+ return to;
+ }
+
+ var updateInProgress = false;
+
+ // Moment prototype object
+ function Moment(config) {
+ copyConfig(this, config);
+ this._d = new Date(+config._d);
+ // Prevent infinite loop in case updateOffset creates new moment
+ // objects.
+ if (updateInProgress === false) {
+ updateInProgress = true;
+ utils_hooks__hooks.updateOffset(this);
+ updateInProgress = false;
+ }
+ }
+
+ function isMoment (obj) {
+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+ }
+
+ function toInt(argumentForCoercion) {
+ var coercedNumber = +argumentForCoercion,
+ value = 0;
+
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+ if (coercedNumber >= 0) {
+ value = Math.floor(coercedNumber);
+ } else {
+ value = Math.ceil(coercedNumber);
+ }
+ }
+
+ return value;
+ }
+
+ function compareArrays(array1, array2, dontConvert) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if ((dontConvert && array1[i] !== array2[i]) ||
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+ }
+
+ function Locale() {
+ }
+
+ var locales = {};
+ var globalLocale;
+
+ function normalizeLocale(key) {
+ return key ? key.toLowerCase().replace('_', '-') : key;
+ }
+
+ // pick the locale from the array
+ // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+ // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+ function chooseLocale(names) {
+ var i = 0, j, next, locale, split;
+
+ while (i < names.length) {
+ split = normalizeLocale(names[i]).split('-');
+ j = split.length;
+ next = normalizeLocale(names[i + 1]);
+ next = next ? next.split('-') : null;
+ while (j > 0) {
+ locale = loadLocale(split.slice(0, j).join('-'));
+ if (locale) {
+ return locale;
+ }
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+ //the next array item is better than a shallower substring of this one
+ break;
+ }
+ j--;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ function loadLocale(name) {
+ var oldLocale = null;
+ // TODO: Find a better way to register and load all the locales in Node
+ if (!locales[name] && typeof module !== 'undefined' &&
+ module && module.exports) {
+ try {
+ oldLocale = globalLocale._abbr;
+ require('./locale/' + name);
+ // because defineLocale currently also sets the global locale, we
+ // want to undo that for lazy loaded locales
+ locale_locales__getSetGlobalLocale(oldLocale);
+ } catch (e) { }
+ }
+ return locales[name];
+ }
+
+ // This function will load locale and then set the global locale. If
+ // no arguments are passed in, it will simply return the current global
+ // locale key.
+ function locale_locales__getSetGlobalLocale (key, values) {
+ var data;
+ if (key) {
+ if (typeof values === 'undefined') {
+ data = locale_locales__getLocale(key);
+ }
+ else {
+ data = defineLocale(key, values);
+ }
+
+ if (data) {
+ // moment.duration._locale = moment._locale = data;
+ globalLocale = data;
+ }
+ }
+
+ return globalLocale._abbr;
+ }
+
+ function defineLocale (name, values) {
+ if (values !== null) {
+ values.abbr = name;
+ if (!locales[name]) {
+ locales[name] = new Locale();
+ }
+ locales[name].set(values);
+
+ // backwards compat for now: also set the locale
+ locale_locales__getSetGlobalLocale(name);
+
+ return locales[name];
+ } else {
+ // useful for testing
+ delete locales[name];
+ return null;
+ }
+ }
+
+ // returns locale data
+ function locale_locales__getLocale (key) {
+ var locale;
+
+ if (key && key._locale && key._locale._abbr) {
+ key = key._locale._abbr;
+ }
+
+ if (!key) {
+ return globalLocale;
+ }
+
+ if (!isArray(key)) {
+ //short-circuit everything else
+ locale = loadLocale(key);
+ if (locale) {
+ return locale;
+ }
+ key = [key];
+ }
+
+ return chooseLocale(key);
+ }
+
+ var aliases = {};
+
+ function addUnitAlias (unit, shorthand) {
+ var lowerCase = unit.toLowerCase();
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+ }
+
+ function normalizeUnits(units) {
+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+ }
+
+ function normalizeObjectUnits(inputObject) {
+ var normalizedInput = {},
+ normalizedProp,
+ prop;
+
+ for (prop in inputObject) {
+ if (hasOwnProp(inputObject, prop)) {
+ normalizedProp = normalizeUnits(prop);
+ if (normalizedProp) {
+ normalizedInput[normalizedProp] = inputObject[prop];
+ }
+ }
+ }
+
+ return normalizedInput;
+ }
+
+ function makeGetSet (unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ get_set__set(this, unit, value);
+ utils_hooks__hooks.updateOffset(this, keepTime);
+ return this;
+ } else {
+ return get_set__get(this, unit);
+ }
+ };
+ }
+
+ function get_set__get (mom, unit) {
+ return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
+ }
+
+ function get_set__set (mom, unit, value) {
+ return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+
+ // MOMENTS
+
+ function getSet (units, value) {
+ var unit;
+ if (typeof units === 'object') {
+ for (unit in units) {
+ this.set(unit, units[unit]);
+ }
+ } else {
+ units = normalizeUnits(units);
+ if (typeof this[units] === 'function') {
+ return this[units](value);
+ }
+ }
+ return this;
+ }
+
+ function zeroFill(number, targetLength, forceSign) {
+ var output = '' + Math.abs(number),
+ sign = number >= 0;
+
+ while (output.length < targetLength) {
+ output = '0' + output;
+ }
+ return (sign ? (forceSign ? '+' : '') : '-') + output;
+ }
+
+ var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g;
+
+ var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
+
+ var formatFunctions = {};
+
+ var formatTokenFunctions = {};
+
+ // token: 'M'
+ // padded: ['MM', 2]
+ // ordinal: 'Mo'
+ // callback: function () { this.month() + 1 }
+ function addFormatToken (token, padded, ordinal, callback) {
+ var func = callback;
+ if (typeof callback === 'string') {
+ func = function () {
+ return this[callback]();
+ };
+ }
+ if (token) {
+ formatTokenFunctions[token] = func;
+ }
+ if (padded) {
+ formatTokenFunctions[padded[0]] = function () {
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+ };
+ }
+ if (ordinal) {
+ formatTokenFunctions[ordinal] = function () {
+ return this.localeData().ordinal(func.apply(this, arguments), token);
+ };
+ }
+ }
+
+ function removeFormattingTokens(input) {
+ if (input.match(/\[[\s\S]/)) {
+ return input.replace(/^\[|\]$/g, '');
+ }
+ return input.replace(/\\/g, '');
+ }
+
+ function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = '';
+ for (i = 0; i < length; i++) {
+ output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
+ }
+
+ // format date using native date object
+ function formatMoment(m, format) {
+ if (!m.isValid()) {
+ return m.localeData().invalidDate();
+ }
+
+ format = expandFormat(format, m.localeData());
+
+ if (!formatFunctions[format]) {
+ formatFunctions[format] = makeFormatFunction(format);
+ }
+
+ return formatFunctions[format](m);
+ }
+
+ function expandFormat(format, locale) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return locale.longDateFormat(input) || input;
+ }
+
+ localFormattingTokens.lastIndex = 0;
+ while (i >= 0 && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ localFormattingTokens.lastIndex = 0;
+ i -= 1;
+ }
+
+ return format;
+ }
+
+ var match1 = /\d/; // 0 - 9
+ var match2 = /\d\d/; // 00 - 99
+ var match3 = /\d{3}/; // 000 - 999
+ var match4 = /\d{4}/; // 0000 - 9999
+ var match6 = /[+-]?\d{6}/; // -999999 - 999999
+ var match1to2 = /\d\d?/; // 0 - 99
+ var match1to3 = /\d{1,3}/; // 0 - 999
+ var match1to4 = /\d{1,4}/; // 0 - 9999
+ var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
+
+ var matchUnsigned = /\d+/; // 0 - inf
+ var matchSigned = /[+-]?\d+/; // -inf - inf
+
+ var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+
+ var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+ // any word (or two) characters or numbers including two/three word month in arabic.
+ var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
+
+ var regexes = {};
+
+ function addRegexToken (token, regex, strictRegex) {
+ regexes[token] = typeof regex === 'function' ? regex : function (isStrict) {
+ return (isStrict && strictRegex) ? strictRegex : regex;
+ };
+ }
+
+ function getParseRegexForToken (token, config) {
+ if (!hasOwnProp(regexes, token)) {
+ return new RegExp(unescapeFormat(token));
+ }
+
+ return regexes[token](config._strict, config._locale);
+ }
+
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+ function unescapeFormat(s) {
+ return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+ return p1 || p2 || p3 || p4;
+ }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+ }
+
+ var tokens = {};
+
+ function addParseToken (token, callback) {
+ var i, func = callback;
+ if (typeof token === 'string') {
+ token = [token];
+ }
+ if (typeof callback === 'number') {
+ func = function (input, array) {
+ array[callback] = toInt(input);
+ };
+ }
+ for (i = 0; i < token.length; i++) {
+ tokens[token[i]] = func;
+ }
+ }
+
+ function addWeekParseToken (token, callback) {
+ addParseToken(token, function (input, array, config, token) {
+ config._w = config._w || {};
+ callback(input, config._w, config, token);
+ });
+ }
+
+ function addTimeToArrayFromToken(token, input, config) {
+ if (input != null && hasOwnProp(tokens, token)) {
+ tokens[token](input, config._a, config, token);
+ }
+ }
+
+ var YEAR = 0;
+ var MONTH = 1;
+ var DATE = 2;
+ var HOUR = 3;
+ var MINUTE = 4;
+ var SECOND = 5;
+ var MILLISECOND = 6;
+
+ function daysInMonth(year, month) {
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
+ }
+
+ // FORMATTING
+
+ addFormatToken('M', ['MM', 2], 'Mo', function () {
+ return this.month() + 1;
+ });
+
+ addFormatToken('MMM', 0, 0, function (format) {
+ return this.localeData().monthsShort(this, format);
+ });
+
+ addFormatToken('MMMM', 0, 0, function (format) {
+ return this.localeData().months(this, format);
+ });
+
+ // ALIASES
+
+ addUnitAlias('month', 'M');
+
+ // PARSING
+
+ addRegexToken('M', match1to2);
+ addRegexToken('MM', match1to2, match2);
+ addRegexToken('MMM', matchWord);
+ addRegexToken('MMMM', matchWord);
+
+ addParseToken(['M', 'MM'], function (input, array) {
+ array[MONTH] = toInt(input) - 1;
+ });
+
+ addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
+ var month = config._locale.monthsParse(input, token, config._strict);
+ // if we didn't find a month name, mark the date as invalid.
+ if (month != null) {
+ array[MONTH] = month;
+ } else {
+ getParsingFlags(config).invalidMonth = input;
+ }
+ });
+
+ // LOCALES
+
+ var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
+ function localeMonths (m) {
+ return this._months[m.month()];
+ }
+
+ var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
+ function localeMonthsShort (m) {
+ return this._monthsShort[m.month()];
+ }
+
+ function localeMonthsParse (monthName, format, strict) {
+ var i, mom, regex;
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ }
+
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = create_utc__createUTC([2000, i]);
+ if (strict && !this._longMonthsParse[i]) {
+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
+ }
+ if (!strict && !this._monthsParse[i]) {
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function setMonth (mom, value) {
+ var dayOfMonth;
+
+ // TODO: Move this out of here!
+ if (typeof value === 'string') {
+ value = mom.localeData().monthsParse(value);
+ // TODO: Another silent failure?
+ if (typeof value !== 'number') {
+ return mom;
+ }
+ }
+
+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ return mom;
+ }
+
+ function getSetMonth (value) {
+ if (value != null) {
+ setMonth(this, value);
+ utils_hooks__hooks.updateOffset(this, true);
+ return this;
+ } else {
+ return get_set__get(this, 'Month');
+ }
+ }
+
+ function getDaysInMonth () {
+ return daysInMonth(this.year(), this.month());
+ }
+
+ function checkOverflow (m) {
+ var overflow;
+ var a = m._a;
+
+ if (a && getParsingFlags(m).overflow === -2) {
+ overflow =
+ a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
+ a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
+ a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
+ a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
+ a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
+ a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
+ -1;
+
+ if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+ overflow = DATE;
+ }
+
+ getParsingFlags(m).overflow = overflow;
+ }
+
+ return m;
+ }
+
+ function warn(msg) {
+ if (utils_hooks__hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
+ console.warn('Deprecation warning: ' + msg);
+ }
+ }
+
+ function deprecate(msg, fn) {
+ var firstTime = true,
+ msgWithStack = msg + '\n' + (new Error()).stack;
+
+ return extend(function () {
+ if (firstTime) {
+ warn(msgWithStack);
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+ }
+
+ var deprecations = {};
+
+ function deprecateSimple(name, msg) {
+ if (!deprecations[name]) {
+ warn(msg);
+ deprecations[name] = true;
+ }
+ }
+
+ utils_hooks__hooks.suppressDeprecationWarnings = false;
+
+ var from_string__isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
+
+ var isoDates = [
+ ['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}/]
+ ];
+
+ // iso time formats and regexes
+ var isoTimes = [
+ ['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/]
+ ];
+
+ var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
+
+ // date from iso format
+ function configFromISO(config) {
+ var i, l,
+ string = config._i,
+ match = from_string__isoRegex.exec(string);
+
+ if (match) {
+ getParsingFlags(config).iso = true;
+ for (i = 0, l = isoDates.length; i < l; i++) {
+ if (isoDates[i][1].exec(string)) {
+ // match[5] should be 'T' or undefined
+ config._f = isoDates[i][0] + (match[6] || ' ');
+ break;
+ }
+ }
+ for (i = 0, l = isoTimes.length; i < l; i++) {
+ if (isoTimes[i][1].exec(string)) {
+ config._f += isoTimes[i][0];
+ break;
+ }
+ }
+ if (string.match(matchOffset)) {
+ config._f += 'Z';
+ }
+ configFromStringAndFormat(config);
+ } else {
+ config._isValid = false;
+ }
+ }
+
+ // date from iso format or fallback
+ function configFromString(config) {
+ var matched = aspNetJsonRegex.exec(config._i);
+
+ if (matched !== null) {
+ config._d = new Date(+matched[1]);
+ return;
+ }
+
+ configFromISO(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ utils_hooks__hooks.createFromInputFallback(config);
+ }
+ }
+
+ utils_hooks__hooks.createFromInputFallback = deprecate(
+ '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 (config) {
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+ }
+ );
+
+ function createDate (y, m, d, h, M, s, ms) {
+ //can't just apply() to create a date:
+ //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
+ var date = new Date(y, m, d, h, M, s, ms);
+
+ //the date constructor doesn't accept years < 1970
+ if (y < 1970) {
+ date.setFullYear(y);
+ }
+ return date;
+ }
+
+ function createUTCDate (y) {
+ var date = new Date(Date.UTC.apply(null, arguments));
+ if (y < 1970) {
+ date.setUTCFullYear(y);
+ }
+ return date;
+ }
+
+ addFormatToken(0, ['YY', 2], 0, function () {
+ return this.year() % 100;
+ });
+
+ addFormatToken(0, ['YYYY', 4], 0, 'year');
+ addFormatToken(0, ['YYYYY', 5], 0, 'year');
+ addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+ // ALIASES
+
+ addUnitAlias('year', 'y');
+
+ // PARSING
+
+ addRegexToken('Y', matchSigned);
+ addRegexToken('YY', match1to2, match2);
+ addRegexToken('YYYY', match1to4, match4);
+ addRegexToken('YYYYY', match1to6, match6);
+ addRegexToken('YYYYYY', match1to6, match6);
+
+ addParseToken(['YYYY', 'YYYYY', 'YYYYYY'], YEAR);
+ addParseToken('YY', function (input, array) {
+ array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
+ });
+
+ // HELPERS
+
+ function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+ }
+
+ function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ }
+
+ // HOOKS
+
+ utils_hooks__hooks.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+ };
+
+ // MOMENTS
+
+ var getSetYear = makeGetSet('FullYear', false);
+
+ function getIsLeapYear () {
+ return isLeapYear(this.year());
+ }
+
+ addFormatToken('w', ['ww', 2], 'wo', 'week');
+ addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+ // ALIASES
+
+ addUnitAlias('week', 'w');
+ addUnitAlias('isoWeek', 'W');
+
+ // PARSING
+
+ addRegexToken('w', match1to2);
+ addRegexToken('ww', match1to2, match2);
+ addRegexToken('W', match1to2);
+ addRegexToken('WW', match1to2, match2);
+
+ addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
+ week[token.substr(0, 1)] = toInt(input);
+ });
+
+ // HELPERS
+
+ // firstDayOfWeek 0 = sun, 6 = sat
+ // the day of the week that starts the week
+ // (usually sunday or monday)
+ // firstDayOfWeekOfYear 0 = sun, 6 = sat
+ // the first week is the week that contains the first
+ // of this day of the week
+ // (eg. ISO weeks use thursday (4))
+ function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
+ var end = firstDayOfWeekOfYear - firstDayOfWeek,
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
+ adjustedMoment;
+
+
+ if (daysToDayOfWeek > end) {
+ daysToDayOfWeek -= 7;
+ }
+
+ if (daysToDayOfWeek < end - 7) {
+ daysToDayOfWeek += 7;
+ }
+
+ adjustedMoment = local__createLocal(mom).add(daysToDayOfWeek, 'd');
+ return {
+ week: Math.ceil(adjustedMoment.dayOfYear() / 7),
+ year: adjustedMoment.year()
+ };
+ }
+
+ // LOCALES
+
+ function localeWeek (mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
+ }
+
+ var defaultLocaleWeek = {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ };
+
+ function localeFirstDayOfWeek () {
+ return this._week.dow;
+ }
+
+ function localeFirstDayOfYear () {
+ return this._week.doy;
+ }
+
+ // MOMENTS
+
+ function getSetWeek (input) {
+ var week = this.localeData().week(this);
+ return input == null ? week : this.add((input - week) * 7, 'd');
+ }
+
+ function getSetISOWeek (input) {
+ var week = weekOfYear(this, 1, 4).week;
+ return input == null ? week : this.add((input - week) * 7, 'd');
+ }
+
+ addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+ // ALIASES
+
+ addUnitAlias('dayOfYear', 'DDD');
+
+ // PARSING
+
+ addRegexToken('DDD', match1to3);
+ addRegexToken('DDDD', match3);
+ addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+ config._dayOfYear = toInt(input);
+ });
+
+ // HELPERS
+
+ //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+ function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
+ var d = createUTCDate(year, 0, 1).getUTCDay();
+ var daysToAdd;
+ var dayOfYear;
+
+ d = d === 0 ? 7 : d;
+ weekday = weekday != null ? weekday : firstDayOfWeek;
+ daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
+ dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
+
+ return {
+ year : dayOfYear > 0 ? year : year - 1,
+ dayOfYear : dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
+ };
+ }
+
+ // MOMENTS
+
+ function getSetDayOfYear (input) {
+ var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
+ return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
+ }
+
+ // Pick the first defined of two or three arguments.
+ function defaults(a, b, c) {
+ if (a != null) {
+ return a;
+ }
+ if (b != null) {
+ return b;
+ }
+ return c;
+ }
+
+ function currentDateArray(config) {
+ var now = new Date();
+ if (config._useUTC) {
+ return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()];
+ }
+ return [now.getFullYear(), now.getMonth(), now.getDate()];
+ }
+
+ // convert an array to a date.
+ // the array should mirror the parameters below
+ // note: all values past the year are optional and will default to the lowest possible value.
+ // [year, month, day , hour, minute, second, millisecond]
+ function configFromArray (config) {
+ var i, date, input = [], currentDate, yearToUse;
+
+ if (config._d) {
+ return;
+ }
+
+ currentDate = currentDateArray(config);
+
+ //compute day of the year from weeks and weekdays
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+ dayOfYearFromWeekInfo(config);
+ }
+
+ //if the day of the year is set, figure out what it is
+ if (config._dayOfYear) {
+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+ if (config._dayOfYear > daysInYear(yearToUse)) {
+ getParsingFlags(config)._overflowDayOfYear = true;
+ }
+
+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
+ config._a[MONTH] = date.getUTCMonth();
+ config._a[DATE] = date.getUTCDate();
+ }
+
+ // Default to current date.
+ // * if no year, month, day of month are given, default to today
+ // * if day of month is given, default month and year
+ // * if month is given, default only year
+ // * if year is given, don't default anything
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
+ config._a[i] = input[i] = currentDate[i];
+ }
+
+ // Zero out whatever was not defaulted, including time
+ for (; i < 7; i++) {
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // Check for 24:00:00.000
+ if (config._a[HOUR] === 24 &&
+ config._a[MINUTE] === 0 &&
+ config._a[SECOND] === 0 &&
+ config._a[MILLISECOND] === 0) {
+ config._nextDay = true;
+ config._a[HOUR] = 0;
+ }
+
+ config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+ // Apply timezone offset from input. The actual utcOffset can be changed
+ // with parseZone.
+ if (config._tzm != null) {
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+ }
+
+ if (config._nextDay) {
+ config._a[HOUR] = 24;
+ }
+ }
+
+ function dayOfYearFromWeekInfo(config) {
+ var w, weekYear, week, weekday, dow, doy, temp;
+
+ w = config._w;
+ if (w.GG != null || w.W != null || w.E != null) {
+ dow = 1;
+ doy = 4;
+
+ // TODO: We need to take the current isoWeekYear, but that depends on
+ // how we interpret now (local, utc, fixed offset). So create
+ // a now version of current config (take local/utc/offset flags, and
+ // create now).
+ weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
+ week = defaults(w.W, 1);
+ weekday = defaults(w.E, 1);
+ } else {
+ dow = config._locale._week.dow;
+ doy = config._locale._week.doy;
+
+ weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
+ week = defaults(w.w, 1);
+
+ if (w.d != null) {
+ // weekday -- low day numbers are considered next week
+ weekday = w.d;
+ if (weekday < dow) {
+ ++week;
+ }
+ } else if (w.e != null) {
+ // local weekday -- counting starts from begining of week
+ weekday = w.e + dow;
+ } else {
+ // default to begining of week
+ weekday = dow;
+ }
+ }
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
+
+ config._a[YEAR] = temp.year;
+ config._dayOfYear = temp.dayOfYear;
+ }
+
+ utils_hooks__hooks.ISO_8601 = function () {};
+
+ // date from string and format string
+ function configFromStringAndFormat(config) {
+ // TODO: Move this to another part of the creation flow to prevent circular deps
+ if (config._f === utils_hooks__hooks.ISO_8601) {
+ configFromISO(config);
+ return;
+ }
+
+ config._a = [];
+ getParsingFlags(config).empty = true;
+
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var string = '' + config._i,
+ i, parsedInput, tokens, token, skipped,
+ stringLength = string.length,
+ totalParsedInputLength = 0;
+
+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
+
+ for (i = 0; i < tokens.length; i++) {
+ token = tokens[i];
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+ if (parsedInput) {
+ skipped = string.substr(0, string.indexOf(parsedInput));
+ if (skipped.length > 0) {
+ getParsingFlags(config).unusedInput.push(skipped);
+ }
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+ totalParsedInputLength += parsedInput.length;
+ }
+ // don't parse if it's not a known token
+ if (formatTokenFunctions[token]) {
+ if (parsedInput) {
+ getParsingFlags(config).empty = false;
+ }
+ else {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ addTimeToArrayFromToken(token, parsedInput, config);
+ }
+ else if (config._strict && !parsedInput) {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ }
+
+ // add remaining unparsed input length to the string
+ getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+ if (string.length > 0) {
+ getParsingFlags(config).unusedInput.push(string);
+ }
+
+ // clear _12h flag if hour is <= 12
+ if (getParsingFlags(config).bigHour === true &&
+ config._a[HOUR] <= 12 &&
+ config._a[HOUR] > 0) {
+ getParsingFlags(config).bigHour = undefined;
+ }
+ // handle meridiem
+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
+
+ configFromArray(config);
+ checkOverflow(config);
+ }
+
+
+ function meridiemFixWrap (locale, hour, meridiem) {
+ var isPm;
+
+ if (meridiem == null) {
+ // nothing to do
+ return hour;
+ }
+ if (locale.meridiemHour != null) {
+ return locale.meridiemHour(hour, meridiem);
+ } else if (locale.isPM != null) {
+ // Fallback
+ isPm = locale.isPM(meridiem);
+ if (isPm && hour < 12) {
+ hour += 12;
+ }
+ if (!isPm && hour === 12) {
+ hour = 0;
+ }
+ return hour;
+ } else {
+ // this is not supposed to happen
+ return hour;
+ }
+ }
+
+ function configFromStringAndArray(config) {
+ var tempConfig,
+ bestMoment,
+
+ scoreToBeat,
+ i,
+ currentScore;
+
+ if (config._f.length === 0) {
+ getParsingFlags(config).invalidFormat = true;
+ config._d = new Date(NaN);
+ return;
+ }
+
+ for (i = 0; i < config._f.length; i++) {
+ currentScore = 0;
+ tempConfig = copyConfig({}, config);
+ if (config._useUTC != null) {
+ tempConfig._useUTC = config._useUTC;
+ }
+ tempConfig._f = config._f[i];
+ configFromStringAndFormat(tempConfig);
+
+ if (!valid__isValid(tempConfig)) {
+ continue;
+ }
+
+ // if there is any input that was not parsed add a penalty for that format
+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+ //or tokens
+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
+
+ getParsingFlags(tempConfig).score = currentScore;
+
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempConfig;
+ }
+ }
+
+ extend(config, bestMoment || tempConfig);
+ }
+
+ function configFromObject(config) {
+ if (config._d) {
+ return;
+ }
+
+ var i = normalizeObjectUnits(config._i);
+ config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond];
+
+ configFromArray(config);
+ }
+
+ function createFromConfig (config) {
+ var input = config._i,
+ format = config._f,
+ res;
+
+ config._locale = config._locale || locale_locales__getLocale(config._l);
+
+ if (input === null || (format === undefined && input === '')) {
+ return valid__createInvalid({nullInput: true});
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = config._locale.preparse(input);
+ }
+
+ if (isMoment(input)) {
+ return new Moment(checkOverflow(input));
+ } else if (isArray(format)) {
+ configFromStringAndArray(config);
+ } else if (format) {
+ configFromStringAndFormat(config);
+ } else if (isDate(input)) {
+ config._d = input;
+ } else {
+ configFromInput(config);
+ }
+
+ res = new Moment(checkOverflow(config));
+ if (res._nextDay) {
+ // Adding is smart enough around DST
+ res.add(1, 'd');
+ res._nextDay = undefined;
+ }
+
+ return res;
+ }
+
+ function configFromInput(config) {
+ var input = config._i;
+ if (input === undefined) {
+ config._d = new Date();
+ } else if (isDate(input)) {
+ config._d = new Date(+input);
+ } else if (typeof input === 'string') {
+ configFromString(config);
+ } else if (isArray(input)) {
+ config._a = map(input.slice(0), function (obj) {
+ return parseInt(obj, 10);
+ });
+ configFromArray(config);
+ } else if (typeof(input) === 'object') {
+ configFromObject(config);
+ } else if (typeof(input) === 'number') {
+ // from milliseconds
+ config._d = new Date(input);
+ } else {
+ utils_hooks__hooks.createFromInputFallback(config);
+ }
+ }
+
+ function createLocalOrUTC (input, format, locale, strict, isUTC) {
+ var c = {};
+
+ if (typeof(locale) === 'boolean') {
+ strict = locale;
+ locale = undefined;
+ }
+ // object construction must be done this way.
+ // https://github.com/moment/moment/issues/1423
+ c._isAMomentObject = true;
+ c._useUTC = c._isUTC = isUTC;
+ c._l = locale;
+ c._i = input;
+ c._f = format;
+ c._strict = strict;
+
+ return createFromConfig(c);
+ }
+
+ function local__createLocal (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, false);
+ }
+
+ var prototypeMin = deprecate(
+ 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
+ function () {
+ var other = local__createLocal.apply(null, arguments);
+ return other < this ? this : other;
+ }
+ );
+
+ var prototypeMax = deprecate(
+ 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
+ function () {
+ var other = local__createLocal.apply(null, arguments);
+ return other > this ? this : other;
+ }
+ );
+
+ // Pick a moment m from moments so that m[fn](other) is true for all
+ // other. This relies on the function fn to be transitive.
+ //
+ // moments should either be an array of moment objects or an array, whose
+ // first element is an array of moment objects.
+ function pickBy(fn, moments) {
+ var res, i;
+ if (moments.length === 1 && isArray(moments[0])) {
+ moments = moments[0];
+ }
+ if (!moments.length) {
+ return local__createLocal();
+ }
+ res = moments[0];
+ for (i = 1; i < moments.length; ++i) {
+ if (moments[i][fn](res)) {
+ res = moments[i];
+ }
+ }
+ return res;
+ }
+
+ // TODO: Use [].sort instead?
+ function min () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isBefore', args);
+ }
+
+ function max () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isAfter', args);
+ }
+
+ function Duration (duration) {
+ var normalizedInput = normalizeObjectUnits(duration),
+ years = normalizedInput.year || 0,
+ quarters = normalizedInput.quarter || 0,
+ months = normalizedInput.month || 0,
+ weeks = normalizedInput.week || 0,
+ days = normalizedInput.day || 0,
+ hours = normalizedInput.hour || 0,
+ minutes = normalizedInput.minute || 0,
+ seconds = normalizedInput.second || 0,
+ milliseconds = normalizedInput.millisecond || 0;
+
+ // representation for dateAddRemove
+ this._milliseconds = +milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 36e5; // 1000 * 60 * 60
+ // Because of dateAddRemove treats 24 hours as different from a
+ // day when working around DST, we need to store them separately
+ this._days = +days +
+ weeks * 7;
+ // It is impossible translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = +months +
+ quarters * 3 +
+ years * 12;
+
+ this._data = {};
+
+ this._locale = locale_locales__getLocale();
+
+ this._bubble();
+ }
+
+ function isDuration (obj) {
+ return obj instanceof Duration;
+ }
+
+ function offset (token, separator) {
+ addFormatToken(token, 0, 0, function () {
+ var offset = this.utcOffset();
+ var sign = '+';
+ if (offset < 0) {
+ offset = -offset;
+ sign = '-';
+ }
+ return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
+ });
+ }
+
+ offset('Z', ':');
+ offset('ZZ', '');
+
+ // PARSING
+
+ addRegexToken('Z', matchOffset);
+ addRegexToken('ZZ', matchOffset);
+ addParseToken(['Z', 'ZZ'], function (input, array, config) {
+ config._useUTC = true;
+ config._tzm = offsetFromString(input);
+ });
+
+ // HELPERS
+
+ // timezone chunker
+ // '+10:00' > ['10', '00']
+ // '-1530' > ['-15', '30']
+ var chunkOffset = /([\+\-]|\d\d)/gi;
+
+ function offsetFromString(string) {
+ var matches = ((string || '').match(matchOffset) || []);
+ var chunk = matches[matches.length - 1] || [];
+ var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+ var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+ return parts[0] === '+' ? minutes : -minutes;
+ }
+
+ // Return a moment from input, that is local/utc/zone equivalent to model.
+ function cloneWithOffset(input, model) {
+ var res, diff;
+ if (model._isUTC) {
+ res = model.clone();
+ diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);
+ // Use low-level api, because this fn is low-level api.
+ res._d.setTime(+res._d + diff);
+ utils_hooks__hooks.updateOffset(res, false);
+ return res;
+ } else {
+ return local__createLocal(input).local();
+ }
+ return model._isUTC ? local__createLocal(input).zone(model._offset || 0) : local__createLocal(input).local();
+ }
+
+ function getDateOffset (m) {
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+ // https://github.com/moment/moment/pull/1871
+ return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+ }
+
+ // HOOKS
+
+ // This function will be called whenever a moment is mutated.
+ // It is intended to keep the offset in sync with the timezone.
+ utils_hooks__hooks.updateOffset = function () {};
+
+ // MOMENTS
+
+ // keepLocalTime = true means only change the timezone, without
+ // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+ // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+ // +0200, so we adjust the time as needed, to be valid.
+ //
+ // Keeping the time actually adds/subtracts (one hour)
+ // from the actual represented time. That is why we call updateOffset
+ // a second time. In case it wants us to change the offset again
+ // _changeInProgress == true case, then we have to adjust, because
+ // there is no such time in the given timezone.
+ function getSetOffset (input, keepLocalTime) {
+ var offset = this._offset || 0,
+ localAdjust;
+ if (input != null) {
+ if (typeof input === 'string') {
+ input = offsetFromString(input);
+ }
+ if (Math.abs(input) < 16) {
+ input = input * 60;
+ }
+ if (!this._isUTC && keepLocalTime) {
+ localAdjust = getDateOffset(this);
+ }
+ this._offset = input;
+ this._isUTC = true;
+ if (localAdjust != null) {
+ this.add(localAdjust, 'm');
+ }
+ if (offset !== input) {
+ if (!keepLocalTime || this._changeInProgress) {
+ add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
+ } else if (!this._changeInProgress) {
+ this._changeInProgress = true;
+ utils_hooks__hooks.updateOffset(this, true);
+ this._changeInProgress = null;
+ }
+ }
+ return this;
+ } else {
+ return this._isUTC ? offset : getDateOffset(this);
+ }
+ }
+
+ function getSetZone (input, keepLocalTime) {
+ if (input != null) {
+ if (typeof input !== 'string') {
+ input = -input;
+ }
+
+ this.utcOffset(input, keepLocalTime);
+
+ return this;
+ } else {
+ return -this.utcOffset();
+ }
+ }
+
+ function setOffsetToUTC (keepLocalTime) {
+ return this.utcOffset(0, keepLocalTime);
+ }
+
+ function setOffsetToLocal (keepLocalTime) {
+ if (this._isUTC) {
+ this.utcOffset(0, keepLocalTime);
+ this._isUTC = false;
+
+ if (keepLocalTime) {
+ this.subtract(getDateOffset(this), 'm');
+ }
+ }
+ return this;
+ }
+
+ function setOffsetToParsedOffset () {
+ if (this._tzm) {
+ this.utcOffset(this._tzm);
+ } else if (typeof this._i === 'string') {
+ this.utcOffset(offsetFromString(this._i));
+ }
+ return this;
+ }
+
+ function hasAlignedHourOffset (input) {
+ if (!input) {
+ input = 0;
+ }
+ else {
+ input = local__createLocal(input).utcOffset();
+ }
+
+ return (this.utcOffset() - input) % 60 === 0;
+ }
+
+ function isDaylightSavingTime () {
+ return (
+ this.utcOffset() > this.clone().month(0).utcOffset() ||
+ this.utcOffset() > this.clone().month(5).utcOffset()
+ );
+ }
+
+ function isDaylightSavingTimeShifted () {
+ if (this._a) {
+ var other = this._isUTC ? create_utc__createUTC(this._a) : local__createLocal(this._a);
+ return this.isValid() && compareArrays(this._a, other.toArray()) > 0;
+ }
+
+ return false;
+ }
+
+ function isLocal () {
+ return !this._isUTC;
+ }
+
+ function isUtcOffset () {
+ return this._isUTC;
+ }
+
+ function isUtc () {
+ return this._isUTC && this._offset === 0;
+ }
+
+ var aspNetRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/;
+
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+ var create__isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;
+
+ function create__createDuration (input, key) {
+ var duration = input,
+ // matching against regexp is expensive, do it on demand
+ match = null,
+ sign,
+ ret,
+ diffRes;
+
+ if (isDuration(input)) {
+ duration = {
+ ms : input._milliseconds,
+ d : input._days,
+ M : input._months
+ };
+ } else if (typeof input === 'number') {
+ duration = {};
+ if (key) {
+ duration[key] = input;
+ } else {
+ duration.milliseconds = input;
+ }
+ } else if (!!(match = aspNetRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : 1;
+ duration = {
+ y : 0,
+ d : toInt(match[DATE]) * sign,
+ h : toInt(match[HOUR]) * sign,
+ m : toInt(match[MINUTE]) * sign,
+ s : toInt(match[SECOND]) * sign,
+ ms : toInt(match[MILLISECOND]) * sign
+ };
+ } else if (!!(match = create__isoRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : 1;
+ duration = {
+ y : parseIso(match[2], sign),
+ M : parseIso(match[3], sign),
+ d : parseIso(match[4], sign),
+ h : parseIso(match[5], sign),
+ m : parseIso(match[6], sign),
+ s : parseIso(match[7], sign),
+ w : parseIso(match[8], sign)
+ };
+ } else if (duration == null) {// checks for null or undefined
+ duration = {};
+ } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+ diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
+
+ duration = {};
+ duration.ms = diffRes.milliseconds;
+ duration.M = diffRes.months;
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
+ ret._locale = input._locale;
+ }
+
+ return ret;
+ }
+
+ create__createDuration.fn = Duration.prototype;
+
+ function parseIso (inp, sign) {
+ // We'd normally use ~~inp for this, but unfortunately it also
+ // converts floats to ints.
+ // inp may be undefined, so careful calling replace on it.
+ var res = inp && parseFloat(inp.replace(',', '.'));
+ // apply sign while we're at it
+ return (isNaN(res) ? 0 : res) * sign;
+ }
+
+ function positiveMomentsDifference(base, other) {
+ var res = {milliseconds: 0, months: 0};
+
+ res.months = other.month() - base.month() +
+ (other.year() - base.year()) * 12;
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
+ --res.months;
+ }
+
+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
+
+ return res;
+ }
+
+ function momentsDifference(base, other) {
+ var res;
+ other = cloneWithOffset(other, base);
+ if (base.isBefore(other)) {
+ res = positiveMomentsDifference(base, other);
+ } else {
+ res = positiveMomentsDifference(other, base);
+ res.milliseconds = -res.milliseconds;
+ res.months = -res.months;
+ }
+
+ return res;
+ }
+
+ function createAdder(direction, name) {
+ return function (val, period) {
+ var dur, tmp;
+ //invert the arguments, but complain about it
+ if (period !== null && !isNaN(+period)) {
+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
+ tmp = val; val = period; period = tmp;
+ }
+
+ val = typeof val === 'string' ? +val : val;
+ dur = create__createDuration(val, period);
+ add_subtract__addSubtract(this, dur, direction);
+ return this;
+ };
+ }
+
+ function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
+ var milliseconds = duration._milliseconds,
+ days = duration._days,
+ months = duration._months;
+ updateOffset = updateOffset == null ? true : updateOffset;
+
+ if (milliseconds) {
+ mom._d.setTime(+mom._d + milliseconds * isAdding);
+ }
+ if (days) {
+ get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
+ }
+ if (months) {
+ setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
+ }
+ if (updateOffset) {
+ utils_hooks__hooks.updateOffset(mom, days || months);
+ }
+ }
+
+ var add_subtract__add = createAdder(1, 'add');
+ var add_subtract__subtract = createAdder(-1, 'subtract');
+
+ function moment_calendar__calendar (time) {
+ // We want to compare the start of today, vs this.
+ // Getting start-of-today depends on whether we're local/utc/offset or not.
+ var now = time || local__createLocal(),
+ sod = cloneWithOffset(now, this).startOf('day'),
+ diff = this.diff(sod, 'days', true),
+ format = diff < -6 ? 'sameElse' :
+ diff < -1 ? 'lastWeek' :
+ diff < 0 ? 'lastDay' :
+ diff < 1 ? 'sameDay' :
+ diff < 2 ? 'nextDay' :
+ diff < 7 ? 'nextWeek' : 'sameElse';
+ return this.format(this.localeData().calendar(format, this, local__createLocal(now)));
+ }
+
+ function clone () {
+ return new Moment(this);
+ }
+
+ function isAfter (input, units) {
+ var inputMs;
+ units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
+ if (units === 'millisecond') {
+ input = isMoment(input) ? input : local__createLocal(input);
+ return +this > +input;
+ } else {
+ inputMs = isMoment(input) ? +input : +local__createLocal(input);
+ return inputMs < +this.clone().startOf(units);
+ }
+ }
+
+ function isBefore (input, units) {
+ var inputMs;
+ units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
+ if (units === 'millisecond') {
+ input = isMoment(input) ? input : local__createLocal(input);
+ return +this < +input;
+ } else {
+ inputMs = isMoment(input) ? +input : +local__createLocal(input);
+ return +this.clone().endOf(units) < inputMs;
+ }
+ }
+
+ function isBetween (from, to, units) {
+ return this.isAfter(from, units) && this.isBefore(to, units);
+ }
+
+ function isSame (input, units) {
+ var inputMs;
+ units = normalizeUnits(units || 'millisecond');
+ if (units === 'millisecond') {
+ input = isMoment(input) ? input : local__createLocal(input);
+ return +this === +input;
+ } else {
+ inputMs = +local__createLocal(input);
+ return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
+ }
+ }
+
+ function absFloor (number) {
+ if (number < 0) {
+ return Math.ceil(number);
+ } else {
+ return Math.floor(number);
+ }
+ }
+
+ function diff (input, units, asFloat) {
+ var that = cloneWithOffset(input, this),
+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4,
+ delta, output;
+
+ units = normalizeUnits(units);
+
+ if (units === 'year' || units === 'month' || units === 'quarter') {
+ output = monthDiff(this, that);
+ if (units === 'quarter') {
+ output = output / 3;
+ } else if (units === 'year') {
+ output = output / 12;
+ }
+ } else {
+ delta = this - that;
+ output = units === 'second' ? delta / 1e3 : // 1000
+ units === 'minute' ? delta / 6e4 : // 1000 * 60
+ units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
+ units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
+ units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
+ delta;
+ }
+ return asFloat ? output : absFloor(output);
+ }
+
+ function monthDiff (a, b) {
+ // difference in months
+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+ // b is in (anchor - 1 month, anchor + 1 month)
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
+ anchor2, adjust;
+
+ if (b - anchor < 0) {
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor - anchor2);
+ } else {
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor2 - anchor);
+ }
+
+ return -(wholeMonthDiff + adjust);
+ }
+
+ utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+
+ function toString () {
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+ }
+
+ function moment_format__toISOString () {
+ var m = this.clone().utc();
+ if (0 < m.year() && m.year() <= 9999) {
+ if ('function' === typeof Date.prototype.toISOString) {
+ // native implementation is ~50x faster, use it when we can
+ return this.toDate().toISOString();
+ } else {
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+ }
+ } else {
+ return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+ }
+ }
+
+ function format (inputString) {
+ var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);
+ return this.localeData().postformat(output);
+ }
+
+ function from (time, withoutSuffix) {
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+ return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+ }
+
+ function fromNow (withoutSuffix) {
+ return this.from(local__createLocal(), withoutSuffix);
+ }
+
+ function to (time, withoutSuffix) {
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+ return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+ }
+
+ function toNow (withoutSuffix) {
+ return this.to(local__createLocal(), withoutSuffix);
+ }
+
+ function locale (key) {
+ var newLocaleData;
+
+ if (key === undefined) {
+ return this._locale._abbr;
+ } else {
+ newLocaleData = locale_locales__getLocale(key);
+ if (newLocaleData != null) {
+ this._locale = newLocaleData;
+ }
+ return this;
+ }
+ }
+
+ var lang = deprecate(
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
+ function (key) {
+ if (key === undefined) {
+ return this.localeData();
+ } else {
+ return this.locale(key);
+ }
+ }
+ );
+
+ function localeData () {
+ return this._locale;
+ }
+
+ function startOf (units) {
+ units = normalizeUnits(units);
+ // the following switch intentionally omits break keywords
+ // to utilize falling through the cases.
+ switch (units) {
+ case 'year':
+ this.month(0);
+ /* falls through */
+ case 'quarter':
+ case 'month':
+ this.date(1);
+ /* falls through */
+ case 'week':
+ case 'isoWeek':
+ case 'day':
+ this.hours(0);
+ /* falls through */
+ case 'hour':
+ this.minutes(0);
+ /* falls through */
+ case 'minute':
+ this.seconds(0);
+ /* falls through */
+ case 'second':
+ this.milliseconds(0);
+ }
+
+ // weeks are a special case
+ if (units === 'week') {
+ this.weekday(0);
+ }
+ if (units === 'isoWeek') {
+ this.isoWeekday(1);
+ }
+
+ // quarters are also special
+ if (units === 'quarter') {
+ this.month(Math.floor(this.month() / 3) * 3);
+ }
+
+ return this;
+ }
+
+ function endOf (units) {
+ units = normalizeUnits(units);
+ if (units === undefined || units === 'millisecond') {
+ return this;
+ }
+ return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+ }
+
+ function to_type__valueOf () {
+ return +this._d - ((this._offset || 0) * 60000);
+ }
+
+ function unix () {
+ return Math.floor(+this / 1000);
+ }
+
+ function toDate () {
+ return this._offset ? new Date(+this) : this._d;
+ }
+
+ function toArray () {
+ var m = this;
+ return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
+ }
+
+ function moment_valid__isValid () {
+ return valid__isValid(this);
+ }
+
+ function parsingFlags () {
+ return extend({}, getParsingFlags(this));
+ }
+
+ function invalidAt () {
+ return getParsingFlags(this).overflow;
+ }
+
+ addFormatToken(0, ['gg', 2], 0, function () {
+ return this.weekYear() % 100;
+ });
+
+ addFormatToken(0, ['GG', 2], 0, function () {
+ return this.isoWeekYear() % 100;
+ });
+
+ function addWeekYearFormatToken (token, getter) {
+ addFormatToken(0, [token, token.length], 0, getter);
+ }
+
+ addWeekYearFormatToken('gggg', 'weekYear');
+ addWeekYearFormatToken('ggggg', 'weekYear');
+ addWeekYearFormatToken('GGGG', 'isoWeekYear');
+ addWeekYearFormatToken('GGGGG', 'isoWeekYear');
+
+ // ALIASES
+
+ addUnitAlias('weekYear', 'gg');
+ addUnitAlias('isoWeekYear', 'GG');
+
+ // PARSING
+
+ addRegexToken('G', matchSigned);
+ addRegexToken('g', matchSigned);
+ addRegexToken('GG', match1to2, match2);
+ addRegexToken('gg', match1to2, match2);
+ addRegexToken('GGGG', match1to4, match4);
+ addRegexToken('gggg', match1to4, match4);
+ addRegexToken('GGGGG', match1to6, match6);
+ addRegexToken('ggggg', match1to6, match6);
+
+ addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
+ week[token.substr(0, 2)] = toInt(input);
+ });
+
+ addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
+ week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
+ });
+
+ // HELPERS
+
+ function weeksInYear(year, dow, doy) {
+ return weekOfYear(local__createLocal([year, 11, 31 + dow - doy]), dow, doy).week;
+ }
+
+ // MOMENTS
+
+ function getSetWeekYear (input) {
+ var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
+ return input == null ? year : this.add((input - year), 'y');
+ }
+
+ function getSetISOWeekYear (input) {
+ var year = weekOfYear(this, 1, 4).year;
+ return input == null ? year : this.add((input - year), 'y');
+ }
+
+ function getISOWeeksInYear () {
+ return weeksInYear(this.year(), 1, 4);
+ }
+
+ function getWeeksInYear () {
+ var weekInfo = this.localeData()._week;
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+ }
+
+ addFormatToken('Q', 0, 0, 'quarter');
+
+ // ALIASES
+
+ addUnitAlias('quarter', 'Q');
+
+ // PARSING
+
+ addRegexToken('Q', match1);
+ addParseToken('Q', function (input, array) {
+ array[MONTH] = (toInt(input) - 1) * 3;
+ });
+
+ // MOMENTS
+
+ function getSetQuarter (input) {
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+ }
+
+ addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+ // ALIASES
+
+ addUnitAlias('date', 'D');
+
+ // PARSING
+
+ addRegexToken('D', match1to2);
+ addRegexToken('DD', match1to2, match2);
+ addRegexToken('Do', function (isStrict, locale) {
+ return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
+ });
+
+ addParseToken(['D', 'DD'], DATE);
+ addParseToken('Do', function (input, array) {
+ array[DATE] = toInt(input.match(match1to2)[0], 10);
+ });
+
+ // MOMENTS
+
+ var getSetDayOfMonth = makeGetSet('Date', true);
+
+ addFormatToken('d', 0, 'do', 'day');
+
+ addFormatToken('dd', 0, 0, function (format) {
+ return this.localeData().weekdaysMin(this, format);
+ });
+
+ addFormatToken('ddd', 0, 0, function (format) {
+ return this.localeData().weekdaysShort(this, format);
+ });
+
+ addFormatToken('dddd', 0, 0, function (format) {
+ return this.localeData().weekdays(this, format);
+ });
+
+ addFormatToken('e', 0, 0, 'weekday');
+ addFormatToken('E', 0, 0, 'isoWeekday');
+
+ // ALIASES
+
+ addUnitAlias('day', 'd');
+ addUnitAlias('weekday', 'e');
+ addUnitAlias('isoWeekday', 'E');
+
+ // PARSING
+
+ addRegexToken('d', match1to2);
+ addRegexToken('e', match1to2);
+ addRegexToken('E', match1to2);
+ addRegexToken('dd', matchWord);
+ addRegexToken('ddd', matchWord);
+ addRegexToken('dddd', matchWord);
+
+ addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) {
+ var weekday = config._locale.weekdaysParse(input);
+ // if we didn't get a weekday name, mark the date as invalid
+ if (weekday != null) {
+ week.d = weekday;
+ } else {
+ getParsingFlags(config).invalidWeekday = input;
+ }
+ });
+
+ addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+ week[token] = toInt(input);
+ });
+
+ // HELPERS
+
+ function parseWeekday(input, locale) {
+ if (typeof input === 'string') {
+ if (!isNaN(input)) {
+ input = parseInt(input, 10);
+ }
+ else {
+ input = locale.weekdaysParse(input);
+ if (typeof input !== 'number') {
+ return null;
+ }
+ }
+ }
+ return input;
+ }
+
+ // LOCALES
+
+ var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+ function localeWeekdays (m) {
+ return this._weekdays[m.day()];
+ }
+
+ var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+ function localeWeekdaysShort (m) {
+ return this._weekdaysShort[m.day()];
+ }
+
+ var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+ function localeWeekdaysMin (m) {
+ return this._weekdaysMin[m.day()];
+ }
+
+ function localeWeekdaysParse (weekdayName) {
+ var i, mom, regex;
+
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ }
+
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+ if (!this._weekdaysParse[i]) {
+ mom = local__createLocal([2000, 1]).day(i);
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (this._weekdaysParse[i].test(weekdayName)) {
+ return i;
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function getSetDayOfWeek (input) {
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ if (input != null) {
+ input = parseWeekday(input, this.localeData());
+ return this.add(input - day, 'd');
+ } else {
+ return day;
+ }
+ }
+
+ function getSetLocaleDayOfWeek (input) {
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+ return input == null ? weekday : this.add(input - weekday, 'd');
+ }
+
+ function getSetISODayOfWeek (input) {
+ // behaves the same as moment#day except
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+ // as a setter, sunday should belong to the previous week.
+ return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
+ }
+
+ addFormatToken('H', ['HH', 2], 0, 'hour');
+ addFormatToken('h', ['hh', 2], 0, function () {
+ return this.hours() % 12 || 12;
+ });
+
+ function meridiem (token, lowercase) {
+ addFormatToken(token, 0, 0, function () {
+ return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
+ });
+ }
+
+ meridiem('a', true);
+ meridiem('A', false);
+
+ // ALIASES
+
+ addUnitAlias('hour', 'h');
+
+ // PARSING
+
+ function matchMeridiem (isStrict, locale) {
+ return locale._meridiemParse;
+ }
+
+ addRegexToken('a', matchMeridiem);
+ addRegexToken('A', matchMeridiem);
+ addRegexToken('H', match1to2);
+ addRegexToken('h', match1to2);
+ addRegexToken('HH', match1to2, match2);
+ addRegexToken('hh', match1to2, match2);
+
+ addParseToken(['H', 'HH'], HOUR);
+ addParseToken(['a', 'A'], function (input, array, config) {
+ config._isPm = config._locale.isPM(input);
+ config._meridiem = input;
+ });
+ addParseToken(['h', 'hh'], function (input, array, config) {
+ array[HOUR] = toInt(input);
+ getParsingFlags(config).bigHour = true;
+ });
+
+ // LOCALES
+
+ function localeIsPM (input) {
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+ // Using charAt should be more compatible.
+ return ((input + '').toLowerCase().charAt(0) === 'p');
+ }
+
+ var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
+ function localeMeridiem (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+ }
+
+
+ // MOMENTS
+
+ // Setting the hour should keep the time, because the user explicitly
+ // specified which hour he wants. So trying to maintain the same hour (in
+ // a new timezone) makes sense. Adding/subtracting hours does not follow
+ // this rule.
+ var getSetHour = makeGetSet('Hours', true);
+
+ addFormatToken('m', ['mm', 2], 0, 'minute');
+
+ // ALIASES
+
+ addUnitAlias('minute', 'm');
+
+ // PARSING
+
+ addRegexToken('m', match1to2);
+ addRegexToken('mm', match1to2, match2);
+ addParseToken(['m', 'mm'], MINUTE);
+
+ // MOMENTS
+
+ var getSetMinute = makeGetSet('Minutes', false);
+
+ addFormatToken('s', ['ss', 2], 0, 'second');
+
+ // ALIASES
+
+ addUnitAlias('second', 's');
+
+ // PARSING
+
+ addRegexToken('s', match1to2);
+ addRegexToken('ss', match1to2, match2);
+ addParseToken(['s', 'ss'], SECOND);
+
+ // MOMENTS
+
+ var getSetSecond = makeGetSet('Seconds', false);
+
+ addFormatToken('S', 0, 0, function () {
+ return ~~(this.millisecond() / 100);
+ });
+
+ addFormatToken(0, ['SS', 2], 0, function () {
+ return ~~(this.millisecond() / 10);
+ });
+
+ function millisecond__milliseconds (token) {
+ addFormatToken(0, [token, 3], 0, 'millisecond');
+ }
+
+ millisecond__milliseconds('SSS');
+ millisecond__milliseconds('SSSS');
+
+ // ALIASES
+
+ addUnitAlias('millisecond', 'ms');
+
+ // PARSING
+
+ addRegexToken('S', match1to3, match1);
+ addRegexToken('SS', match1to3, match2);
+ addRegexToken('SSS', match1to3, match3);
+ addRegexToken('SSSS', matchUnsigned);
+ addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) {
+ array[MILLISECOND] = toInt(('0.' + input) * 1000);
+ });
+
+ // MOMENTS
+
+ var getSetMillisecond = makeGetSet('Milliseconds', false);
+
+ addFormatToken('z', 0, 0, 'zoneAbbr');
+ addFormatToken('zz', 0, 0, 'zoneName');
+
+ // MOMENTS
+
+ function getZoneAbbr () {
+ return this._isUTC ? 'UTC' : '';
+ }
+
+ function getZoneName () {
+ return this._isUTC ? 'Coordinated Universal Time' : '';
+ }
+
+ var momentPrototype__proto = Moment.prototype;
+
+ momentPrototype__proto.add = add_subtract__add;
+ momentPrototype__proto.calendar = moment_calendar__calendar;
+ momentPrototype__proto.clone = clone;
+ momentPrototype__proto.diff = diff;
+ momentPrototype__proto.endOf = endOf;
+ momentPrototype__proto.format = format;
+ momentPrototype__proto.from = from;
+ momentPrototype__proto.fromNow = fromNow;
+ momentPrototype__proto.to = to;
+ momentPrototype__proto.toNow = toNow;
+ momentPrototype__proto.get = getSet;
+ momentPrototype__proto.invalidAt = invalidAt;
+ momentPrototype__proto.isAfter = isAfter;
+ momentPrototype__proto.isBefore = isBefore;
+ momentPrototype__proto.isBetween = isBetween;
+ momentPrototype__proto.isSame = isSame;
+ momentPrototype__proto.isValid = moment_valid__isValid;
+ momentPrototype__proto.lang = lang;
+ momentPrototype__proto.locale = locale;
+ momentPrototype__proto.localeData = localeData;
+ momentPrototype__proto.max = prototypeMax;
+ momentPrototype__proto.min = prototypeMin;
+ momentPrototype__proto.parsingFlags = parsingFlags;
+ momentPrototype__proto.set = getSet;
+ momentPrototype__proto.startOf = startOf;
+ momentPrototype__proto.subtract = add_subtract__subtract;
+ momentPrototype__proto.toArray = toArray;
+ momentPrototype__proto.toDate = toDate;
+ momentPrototype__proto.toISOString = moment_format__toISOString;
+ momentPrototype__proto.toJSON = moment_format__toISOString;
+ momentPrototype__proto.toString = toString;
+ momentPrototype__proto.unix = unix;
+ momentPrototype__proto.valueOf = to_type__valueOf;
+
+ // Year
+ momentPrototype__proto.year = getSetYear;
+ momentPrototype__proto.isLeapYear = getIsLeapYear;
+
+ // Week Year
+ momentPrototype__proto.weekYear = getSetWeekYear;
+ momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
+
+ // Quarter
+ momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
+
+ // Month
+ momentPrototype__proto.month = getSetMonth;
+ momentPrototype__proto.daysInMonth = getDaysInMonth;
+
+ // Week
+ momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek;
+ momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek;
+ momentPrototype__proto.weeksInYear = getWeeksInYear;
+ momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
+
+ // Day
+ momentPrototype__proto.date = getSetDayOfMonth;
+ momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek;
+ momentPrototype__proto.weekday = getSetLocaleDayOfWeek;
+ momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
+ momentPrototype__proto.dayOfYear = getSetDayOfYear;
+
+ // Hour
+ momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
+
+ // Minute
+ momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
+
+ // Second
+ momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
+
+ // Millisecond
+ momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
+
+ // Offset
+ momentPrototype__proto.utcOffset = getSetOffset;
+ momentPrototype__proto.utc = setOffsetToUTC;
+ momentPrototype__proto.local = setOffsetToLocal;
+ momentPrototype__proto.parseZone = setOffsetToParsedOffset;
+ momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
+ momentPrototype__proto.isDST = isDaylightSavingTime;
+ momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted;
+ momentPrototype__proto.isLocal = isLocal;
+ momentPrototype__proto.isUtcOffset = isUtcOffset;
+ momentPrototype__proto.isUtc = isUtc;
+ momentPrototype__proto.isUTC = isUtc;
+
+ // Timezone
+ momentPrototype__proto.zoneAbbr = getZoneAbbr;
+ momentPrototype__proto.zoneName = getZoneName;
+
+ // Deprecations
+ momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+ momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+ momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+ momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
+
+ var momentPrototype = momentPrototype__proto;
+
+ function moment__createUnix (input) {
+ return local__createLocal(input * 1000);
+ }
+
+ function moment__createInZone () {
+ return local__createLocal.apply(null, arguments).parseZone();
+ }
+
+ var defaultCalendar = {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ };
+
+ function locale_calendar__calendar (key, mom, now) {
+ var output = this._calendar[key];
+ return typeof output === 'function' ? output.call(mom, now) : output;
+ }
+
+ var defaultLongDateFormat = {
+ 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'
+ };
+
+ function longDateFormat (key) {
+ var output = this._longDateFormat[key];
+ if (!output && this._longDateFormat[key.toUpperCase()]) {
+ output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+ this._longDateFormat[key] = output;
+ }
+ return output;
+ }
+
+ var defaultInvalidDate = 'Invalid date';
+
+ function invalidDate () {
+ return this._invalidDate;
+ }
+
+ var defaultOrdinal = '%d';
+ var defaultOrdinalParse = /\d{1,2}/;
+
+ function ordinal (number) {
+ return this._ordinal.replace('%d', number);
+ }
+
+ function preParsePostFormat (string) {
+ return string;
+ }
+
+ var defaultRelativeTime = {
+ 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'
+ };
+
+ function relative__relativeTime (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (typeof output === 'function') ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+ }
+
+ function pastFuture (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
+ }
+
+ function locale_set__set (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (typeof prop === 'function') {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ // Lenient ordinal parsing accepts just a number in addition to
+ // number + (possibly) stuff coming from _ordinalParseLenient.
+ this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
+ }
+
+ var prototype__proto = Locale.prototype;
+
+ prototype__proto._calendar = defaultCalendar;
+ prototype__proto.calendar = locale_calendar__calendar;
+ prototype__proto._longDateFormat = defaultLongDateFormat;
+ prototype__proto.longDateFormat = longDateFormat;
+ prototype__proto._invalidDate = defaultInvalidDate;
+ prototype__proto.invalidDate = invalidDate;
+ prototype__proto._ordinal = defaultOrdinal;
+ prototype__proto.ordinal = ordinal;
+ prototype__proto._ordinalParse = defaultOrdinalParse;
+ prototype__proto.preparse = preParsePostFormat;
+ prototype__proto.postformat = preParsePostFormat;
+ prototype__proto._relativeTime = defaultRelativeTime;
+ prototype__proto.relativeTime = relative__relativeTime;
+ prototype__proto.pastFuture = pastFuture;
+ prototype__proto.set = locale_set__set;
+
+ // Month
+ prototype__proto.months = localeMonths;
+ prototype__proto._months = defaultLocaleMonths;
+ prototype__proto.monthsShort = localeMonthsShort;
+ prototype__proto._monthsShort = defaultLocaleMonthsShort;
+ prototype__proto.monthsParse = localeMonthsParse;
+
+ // Week
+ prototype__proto.week = localeWeek;
+ prototype__proto._week = defaultLocaleWeek;
+ prototype__proto.firstDayOfYear = localeFirstDayOfYear;
+ prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
+
+ // Day of Week
+ prototype__proto.weekdays = localeWeekdays;
+ prototype__proto._weekdays = defaultLocaleWeekdays;
+ prototype__proto.weekdaysMin
<TRUNCATED>
[07/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/moment-2.9.0.min.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/moment-2.9.0.min.js b/htrace-htraced/src/web/lib/js/moment-2.9.0.min.js
deleted file mode 100644
index c7f6dcd..0000000
--- a/htrace-htraced/src/web/lib/js/moment-2.9.0.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-//! moment.js
-//! version : 2.9.0
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-(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,invalidFormat:!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._tz
m=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(th
is,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)}function 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._isVal
id}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.longDate
Format(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;if(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:f
unction(){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._ordinalPa
rse.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,fun
ction(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}/,pr
eparse: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)},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";re
turn 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?("stri
ng"!=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")},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:func
tion(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 inste
ad.",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)
-},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=funct
ion(){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);
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/underscore-1.7.0.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/underscore-1.7.0.js b/htrace-htraced/src/web/lib/js/underscore-1.7.0.js
deleted file mode 100644
index d5b3375..0000000
--- a/htrace-htraced/src/web/lib/js/underscore-1.7.0.js
+++ /dev/null
@@ -1,1416 +0,0 @@
-// Underscore.js 1.7.0
-// http://underscorejs.org
-// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
-// Underscore may be freely distributed under the MIT license.
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `exports` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var
- push = ArrayProto.push,
- slice = ArrayProto.slice,
- concat = ArrayProto.concat,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) {
- if (obj instanceof _) return obj;
- if (!(this instanceof _)) return new _(obj);
- this._wrapped = obj;
- };
-
- // Export the Underscore object for **Node.js**, with
- // backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root._ = _;
- }
-
- // Current version.
- _.VERSION = '1.7.0';
-
- // Internal function that returns an efficient (for current engines) version
- // of the passed-in callback, to be repeatedly applied in other Underscore
- // functions.
- var createCallback = function(func, context, argCount) {
- if (context === void 0) return func;
- switch (argCount == null ? 3 : argCount) {
- case 1: return function(value) {
- return func.call(context, value);
- };
- case 2: return function(value, other) {
- return func.call(context, value, other);
- };
- case 3: return function(value, index, collection) {
- return func.call(context, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(context, accumulator, value, index, collection);
- };
- }
- return function() {
- return func.apply(context, arguments);
- };
- };
-
- // A mostly-internal function to generate callbacks that can be applied
- // to each element in a collection, returning the desired result — either
- // identity, an arbitrary callback, a property matcher, or a property accessor.
- _.iteratee = function(value, context, argCount) {
- if (value == null) return _.identity;
- if (_.isFunction(value)) return createCallback(value, context, argCount);
- if (_.isObject(value)) return _.matches(value);
- return _.property(value);
- };
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles raw objects in addition to array-likes. Treats all
- // sparse array-likes as if they were dense.
- _.each = _.forEach = function(obj, iteratee, context) {
- if (obj == null) return obj;
- iteratee = createCallback(iteratee, context);
- var i, length = obj.length;
- if (length === +length) {
- for (i = 0; i < length; i++) {
- iteratee(obj[i], i, obj);
- }
- } else {
- var keys = _.keys(obj);
- for (i = 0, length = keys.length; i < length; i++) {
- iteratee(obj[keys[i]], keys[i], obj);
- }
- }
- return obj;
- };
-
- // Return the results of applying the iteratee to each element.
- _.map = _.collect = function(obj, iteratee, context) {
- if (obj == null) return [];
- iteratee = _.iteratee(iteratee, context);
- var keys = obj.length !== +obj.length && _.keys(obj),
- length = (keys || obj).length,
- results = Array(length),
- currentKey;
- for (var index = 0; index < length; index++) {
- currentKey = keys ? keys[index] : index;
- results[index] = iteratee(obj[currentKey], currentKey, obj);
- }
- return results;
- };
-
- var reduceError = 'Reduce of empty array with no initial value';
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`.
- _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
- if (obj == null) obj = [];
- iteratee = createCallback(iteratee, context, 4);
- var keys = obj.length !== +obj.length && _.keys(obj),
- length = (keys || obj).length,
- index = 0, currentKey;
- if (arguments.length < 3) {
- if (!length) throw new TypeError(reduceError);
- memo = obj[keys ? keys[index++] : index++];
- }
- for (; index < length; index++) {
- currentKey = keys ? keys[index] : index;
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
- }
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
- if (obj == null) obj = [];
- iteratee = createCallback(iteratee, context, 4);
- var keys = obj.length !== + obj.length && _.keys(obj),
- index = (keys || obj).length,
- currentKey;
- if (arguments.length < 3) {
- if (!index) throw new TypeError(reduceError);
- memo = obj[keys ? keys[--index] : --index];
- }
- while (index--) {
- currentKey = keys ? keys[index] : index;
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
- }
- return memo;
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, predicate, context) {
- var result;
- predicate = _.iteratee(predicate, context);
- _.some(obj, function(value, index, list) {
- if (predicate(value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Aliased as `select`.
- _.filter = _.select = function(obj, predicate, context) {
- var results = [];
- if (obj == null) return results;
- predicate = _.iteratee(predicate, context);
- _.each(obj, function(value, index, list) {
- if (predicate(value, index, list)) results.push(value);
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, predicate, context) {
- return _.filter(obj, _.negate(_.iteratee(predicate)), context);
- };
-
- // Determine whether all of the elements match a truth test.
- // Aliased as `all`.
- _.every = _.all = function(obj, predicate, context) {
- if (obj == null) return true;
- predicate = _.iteratee(predicate, context);
- var keys = obj.length !== +obj.length && _.keys(obj),
- length = (keys || obj).length,
- index, currentKey;
- for (index = 0; index < length; index++) {
- currentKey = keys ? keys[index] : index;
- if (!predicate(obj[currentKey], currentKey, obj)) return false;
- }
- return true;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Aliased as `any`.
- _.some = _.any = function(obj, predicate, context) {
- if (obj == null) return false;
- predicate = _.iteratee(predicate, context);
- var keys = obj.length !== +obj.length && _.keys(obj),
- length = (keys || obj).length,
- index, currentKey;
- for (index = 0; index < length; index++) {
- currentKey = keys ? keys[index] : index;
- if (predicate(obj[currentKey], currentKey, obj)) return true;
- }
- return false;
- };
-
- // Determine if the array or object contains a given value (using `===`).
- // Aliased as `include`.
- _.contains = _.include = function(obj, target) {
- if (obj == null) return false;
- if (obj.length !== +obj.length) obj = _.values(obj);
- return _.indexOf(obj, target) >= 0;
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- var isFunc = _.isFunction(method);
- return _.map(obj, function(value) {
- return (isFunc ? method : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, _.property(key));
- };
-
- // Convenience version of a common use case of `filter`: selecting only objects
- // containing specific `key:value` pairs.
- _.where = function(obj, attrs) {
- return _.filter(obj, _.matches(attrs));
- };
-
- // Convenience version of a common use case of `find`: getting the first object
- // containing specific `key:value` pairs.
- _.findWhere = function(obj, attrs) {
- return _.find(obj, _.matches(attrs));
- };
-
- // Return the maximum element (or element-based computation).
- _.max = function(obj, iteratee, context) {
- var result = -Infinity, lastComputed = -Infinity,
- value, computed;
- if (iteratee == null && obj != null) {
- obj = obj.length === +obj.length ? obj : _.values(obj);
- for (var i = 0, length = obj.length; i < length; i++) {
- value = obj[i];
- if (value > result) {
- result = value;
- }
- }
- } else {
- iteratee = _.iteratee(iteratee, context);
- _.each(obj, function(value, index, list) {
- computed = iteratee(value, index, list);
- if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
- result = value;
- lastComputed = computed;
- }
- });
- }
- return result;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iteratee, context) {
- var result = Infinity, lastComputed = Infinity,
- value, computed;
- if (iteratee == null && obj != null) {
- obj = obj.length === +obj.length ? obj : _.values(obj);
- for (var i = 0, length = obj.length; i < length; i++) {
- value = obj[i];
- if (value < result) {
- result = value;
- }
- }
- } else {
- iteratee = _.iteratee(iteratee, context);
- _.each(obj, function(value, index, list) {
- computed = iteratee(value, index, list);
- if (computed < lastComputed || computed === Infinity && result === Infinity) {
- result = value;
- lastComputed = computed;
- }
- });
- }
- return result;
- };
-
- // Shuffle a collection, using the modern version of the
- // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
- _.shuffle = function(obj) {
- var set = obj && obj.length === +obj.length ? obj : _.values(obj);
- var length = set.length;
- var shuffled = Array(length);
- for (var index = 0, rand; index < length; index++) {
- rand = _.random(0, index);
- if (rand !== index) shuffled[index] = shuffled[rand];
- shuffled[rand] = set[index];
- }
- return shuffled;
- };
-
- // Sample **n** random values from a collection.
- // If **n** is not specified, returns a single random element.
- // The internal `guard` argument allows it to work with `map`.
- _.sample = function(obj, n, guard) {
- if (n == null || guard) {
- if (obj.length !== +obj.length) obj = _.values(obj);
- return obj[_.random(obj.length - 1)];
- }
- return _.shuffle(obj).slice(0, Math.max(0, n));
- };
-
- // Sort the object's values by a criterion produced by an iteratee.
- _.sortBy = function(obj, iteratee, context) {
- iteratee = _.iteratee(iteratee, context);
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value: value,
- index: index,
- criteria: iteratee(value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria;
- var b = right.criteria;
- if (a !== b) {
- if (a > b || a === void 0) return 1;
- if (a < b || b === void 0) return -1;
- }
- return left.index - right.index;
- }), 'value');
- };
-
- // An internal function used for aggregate "group by" operations.
- var group = function(behavior) {
- return function(obj, iteratee, context) {
- var result = {};
- iteratee = _.iteratee(iteratee, context);
- _.each(obj, function(value, index) {
- var key = iteratee(value, index, obj);
- behavior(result, value, key);
- });
- return result;
- };
- };
-
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = group(function(result, value, key) {
- if (_.has(result, key)) result[key].push(value); else result[key] = [value];
- });
-
- // Indexes the object's values by a criterion, similar to `groupBy`, but for
- // when you know that your index values will be unique.
- _.indexBy = group(function(result, value, key) {
- result[key] = value;
- });
-
- // Counts instances of an object that group by a certain criterion. Pass
- // either a string attribute to count by, or a function that returns the
- // criterion.
- _.countBy = group(function(result, value, key) {
- if (_.has(result, key)) result[key]++; else result[key] = 1;
- });
-
- // Use a comparator function to figure out the smallest index at which
- // an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iteratee, context) {
- iteratee = _.iteratee(iteratee, context, 1);
- var value = iteratee(obj);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = low + high >>> 1;
- if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
- }
- return low;
- };
-
- // Safely create a real, live array from anything iterable.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (obj.length === +obj.length) return _.map(obj, _.identity);
- return _.values(obj);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- if (obj == null) return 0;
- return obj.length === +obj.length ? obj.length : _.keys(obj).length;
- };
-
- // Split a collection into two arrays: one whose elements all satisfy the given
- // predicate, and one whose elements all do not satisfy the predicate.
- _.partition = function(obj, predicate, context) {
- predicate = _.iteratee(predicate, context);
- var pass = [], fail = [];
- _.each(obj, function(value, key, obj) {
- (predicate(value, key, obj) ? pass : fail).push(value);
- });
- return [pass, fail];
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
- if (array == null) return void 0;
- if (n == null || guard) return array[0];
- if (n < 0) return [];
- return slice.call(array, 0, n);
- };
-
- // Returns everything but the last entry of the array. Especially useful on
- // the arguments object. Passing **n** will return all the values in
- // the array, excluding the last N. The **guard** check allows it to work with
- // `_.map`.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
- };
-
- // Get the last element of an array. Passing **n** will return the last N
- // values in the array. The **guard** check allows it to work with `_.map`.
- _.last = function(array, n, guard) {
- if (array == null) return void 0;
- if (n == null || guard) return array[array.length - 1];
- return slice.call(array, Math.max(array.length - n, 0));
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
- // Especially useful on the arguments object. Passing an **n** will return
- // the rest N values in the array. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, n == null || guard ? 1 : n);
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, _.identity);
- };
-
- // Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, strict, output) {
- if (shallow && _.every(input, _.isArray)) {
- return concat.apply(output, input);
- }
- for (var i = 0, length = input.length; i < length; i++) {
- var value = input[i];
- if (!_.isArray(value) && !_.isArguments(value)) {
- if (!strict) output.push(value);
- } else if (shallow) {
- push.apply(output, value);
- } else {
- flatten(value, shallow, strict, output);
- }
- }
- return output;
- };
-
- // Flatten out an array, either recursively (by default), or just one level.
- _.flatten = function(array, shallow) {
- return flatten(array, shallow, false, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iteratee, context) {
- if (array == null) return [];
- if (!_.isBoolean(isSorted)) {
- context = iteratee;
- iteratee = isSorted;
- isSorted = false;
- }
- if (iteratee != null) iteratee = _.iteratee(iteratee, context);
- var result = [];
- var seen = [];
- for (var i = 0, length = array.length; i < length; i++) {
- var value = array[i];
- if (isSorted) {
- if (!i || seen !== value) result.push(value);
- seen = value;
- } else if (iteratee) {
- var computed = iteratee(value, i, array);
- if (_.indexOf(seen, computed) < 0) {
- seen.push(computed);
- result.push(value);
- }
- } else if (_.indexOf(result, value) < 0) {
- result.push(value);
- }
- }
- return result;
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(flatten(arguments, true, true, []));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
- if (array == null) return [];
- var result = [];
- var argsLength = arguments.length;
- for (var i = 0, length = array.length; i < length; i++) {
- var item = array[i];
- if (_.contains(result, item)) continue;
- for (var j = 1; j < argsLength; j++) {
- if (!_.contains(arguments[j], item)) break;
- }
- if (j === argsLength) result.push(item);
- }
- return result;
- };
-
- // Take the difference between one array and a number of other arrays.
- // Only the elements present in just the first array will remain.
- _.difference = function(array) {
- var rest = flatten(slice.call(arguments, 1), true, true, []);
- return _.filter(array, function(value){
- return !_.contains(rest, value);
- });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function(array) {
- if (array == null) return [];
- var length = _.max(arguments, 'length').length;
- var results = Array(length);
- for (var i = 0; i < length; i++) {
- results[i] = _.pluck(arguments, i);
- }
- return results;
- };
-
- // Converts lists into objects. Pass either a single array of `[key, value]`
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
- // the corresponding values.
- _.object = function(list, values) {
- if (list == null) return {};
- var result = {};
- for (var i = 0, length = list.length; i < length; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
-
- // Return the position of the first occurrence of an item in an array,
- // or -1 if the item is not included in the array.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i = 0, length = array.length;
- if (isSorted) {
- if (typeof isSorted == 'number') {
- i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
- } else {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- }
- for (; i < length; i++) if (array[i] === item) return i;
- return -1;
- };
-
- _.lastIndexOf = function(array, item, from) {
- if (array == null) return -1;
- var idx = array.length;
- if (typeof from == 'number') {
- idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
- }
- while (--idx >= 0) if (array[idx] === item) return idx;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = step || 1;
-
- var length = Math.max(Math.ceil((stop - start) / step), 0);
- var range = Array(length);
-
- for (var idx = 0; idx < length; idx++, start += step) {
- range[idx] = start;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Reusable constructor function for prototype setting.
- var Ctor = function(){};
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
- // available.
- _.bind = function(func, context) {
- var args, bound;
- if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
- args = slice.call(arguments, 2);
- bound = function() {
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
- Ctor.prototype = func.prototype;
- var self = new Ctor;
- Ctor.prototype = null;
- var result = func.apply(self, args.concat(slice.call(arguments)));
- if (_.isObject(result)) return result;
- return self;
- };
- return bound;
- };
-
- // Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context. _ acts
- // as a placeholder, allowing any combination of arguments to be pre-filled.
- _.partial = function(func) {
- var boundArgs = slice.call(arguments, 1);
- return function() {
- var position = 0;
- var args = boundArgs.slice();
- for (var i = 0, length = args.length; i < length; i++) {
- if (args[i] === _) args[i] = arguments[position++];
- }
- while (position < arguments.length) args.push(arguments[position++]);
- return func.apply(this, args);
- };
- };
-
- // Bind a number of an object's methods to that object. Remaining arguments
- // are the method names to be bound. Useful for ensuring that all callbacks
- // defined on an object belong to it.
- _.bindAll = function(obj) {
- var i, length = arguments.length, key;
- if (length <= 1) throw new Error('bindAll must be passed function names');
- for (i = 1; i < length; i++) {
- key = arguments[i];
- obj[key] = _.bind(obj[key], obj);
- }
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memoize = function(key) {
- var cache = memoize.cache;
- var address = hasher ? hasher.apply(this, arguments) : key;
- if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
- return cache[address];
- };
- memoize.cache = {};
- return memoize;
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){
- return func.apply(null, args);
- }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time. Normally, the throttled function will run
- // as much as it can, without ever going more than once per `wait` duration;
- // but if you'd like to disable the execution on the leading edge, pass
- // `{leading: false}`. To disable execution on the trailing edge, ditto.
- _.throttle = function(func, wait, options) {
- var context, args, result;
- var timeout = null;
- var previous = 0;
- if (!options) options = {};
- var later = function() {
- previous = options.leading === false ? 0 : _.now();
- timeout = null;
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- };
- return function() {
- var now = _.now();
- if (!previous && options.leading === false) previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0 || remaining > wait) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout, args, context, timestamp, result;
-
- var later = function() {
- var last = _.now() - timestamp;
-
- if (last < wait && last > 0) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- }
- }
- };
-
- return function() {
- context = this;
- args = arguments;
- timestamp = _.now();
- var callNow = immediate && !timeout;
- if (!timeout) timeout = setTimeout(later, wait);
- if (callNow) {
- result = func.apply(context, args);
- context = args = null;
- }
-
- return result;
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return _.partial(wrapper, func);
- };
-
- // Returns a negated version of the passed-in predicate.
- _.negate = function(predicate) {
- return function() {
- return !predicate.apply(this, arguments);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var args = arguments;
- var start = args.length - 1;
- return function() {
- var i = start;
- var result = args[start].apply(this, arguments);
- while (i--) result = args[i].call(this, result);
- return result;
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
- };
- };
-
- // Returns a function that will only be executed before being called N times.
- _.before = function(times, func) {
- var memo;
- return function() {
- if (--times > 0) {
- memo = func.apply(this, arguments);
- } else {
- func = null;
- }
- return memo;
- };
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = _.partial(_.before, 2);
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = function(obj) {
- if (!_.isObject(obj)) return [];
- if (nativeKeys) return nativeKeys(obj);
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys.push(key);
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- var keys = _.keys(obj);
- var length = keys.length;
- var values = Array(length);
- for (var i = 0; i < length; i++) {
- values[i] = obj[keys[i]];
- }
- return values;
- };
-
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var keys = _.keys(obj);
- var length = keys.length;
- var pairs = Array(length);
- for (var i = 0; i < length; i++) {
- pairs[i] = [keys[i], obj[keys[i]]];
- }
- return pairs;
- };
-
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- var keys = _.keys(obj);
- for (var i = 0, length = keys.length; i < length; i++) {
- result[obj[keys[i]]] = keys[i];
- }
- return result;
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- if (!_.isObject(obj)) return obj;
- var source, prop;
- for (var i = 1, length = arguments.length; i < length; i++) {
- source = arguments[i];
- for (prop in source) {
- if (hasOwnProperty.call(source, prop)) {
- obj[prop] = source[prop];
- }
- }
- }
- return obj;
- };
-
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj, iteratee, context) {
- var result = {}, key;
- if (obj == null) return result;
- if (_.isFunction(iteratee)) {
- iteratee = createCallback(iteratee, context);
- for (key in obj) {
- var value = obj[key];
- if (iteratee(value, key, obj)) result[key] = value;
- }
- } else {
- var keys = concat.apply([], slice.call(arguments, 1));
- obj = new Object(obj);
- for (var i = 0, length = keys.length; i < length; i++) {
- key = keys[i];
- if (key in obj) result[key] = obj[key];
- }
- }
- return result;
- };
-
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj, iteratee, context) {
- if (_.isFunction(iteratee)) {
- iteratee = _.negate(iteratee);
- } else {
- var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
- iteratee = function(value, key) {
- return !_.contains(keys, key);
- };
- }
- return _.pick(obj, iteratee, context);
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- if (!_.isObject(obj)) return obj;
- for (var i = 1, length = arguments.length; i < length; i++) {
- var source = arguments[i];
- for (var prop in source) {
- if (obj[prop] === void 0) obj[prop] = source[prop];
- }
- }
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Internal recursive comparison function for `isEqual`.
- var eq = function(a, b, aStack, bStack) {
- // Identical objects are equal. `0 === -0`, but they aren't identical.
- // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
- if (a === b) return a !== 0 || 1 / a === 1 / b;
- // A strict comparison is necessary because `null == undefined`.
- if (a == null || b == null) return a === b;
- // Unwrap any wrapped objects.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
- // Compare `[[Class]]` names.
- var className = toString.call(a);
- if (className !== toString.call(b)) return false;
- switch (className) {
- // Strings, numbers, regular expressions, dates, and booleans are compared by value.
- case '[object RegExp]':
- // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return '' + a === '' + b;
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive.
- // Object(NaN) is equivalent to NaN
- if (+a !== +a) return +b !== +b;
- // An `egal` comparison is performed for other numeric values.
- return +a === 0 ? 1 / +a === 1 / b : +a === +b;
- case '[object Date]':
- case '[object Boolean]':
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
- // millisecond representations. Note that invalid dates with millisecond representations
- // of `NaN` are not equivalent.
- return +a === +b;
- }
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = aStack.length;
- while (length--) {
- // Linear search. Performance is inversely proportional to the number of
- // unique nested structures.
- if (aStack[length] === a) return bStack[length] === b;
- }
- // Objects with different constructors are not equivalent, but `Object`s
- // from different frames are.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (
- aCtor !== bCtor &&
- // Handle Object.create(x) cases
- 'constructor' in a && 'constructor' in b &&
- !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
- _.isFunction(bCtor) && bCtor instanceof bCtor)
- ) {
- return false;
- }
- // Add the first object to the stack of traversed objects.
- aStack.push(a);
- bStack.push(b);
- var size, result;
- // Recursively compare objects and arrays.
- if (className === '[object Array]') {
- // Compare array lengths to determine if a deep comparison is necessary.
- size = a.length;
- result = size === b.length;
- if (result) {
- // Deep compare the contents, ignoring non-numeric properties.
- while (size--) {
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
- }
- }
- } else {
- // Deep compare objects.
- var keys = _.keys(a), key;
- size = keys.length;
- // Ensure that both objects contain the same number of properties before comparing deep equality.
- result = _.keys(b).length === size;
- if (result) {
- while (size--) {
- // Deep compare each member
- key = keys[size];
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
- }
- }
- }
- // Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
- return result;
- };
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- return eq(a, b, [], []);
- };
-
- // Is a given array, string, or object empty?
- // An "empty" object has no enumerable own-properties.
- _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType === 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) === '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- var type = typeof obj;
- return type === 'function' || type === 'object' && !!obj;
- };
-
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) === '[object ' + name + ']';
- };
- });
-
- // Define a fallback version of the method in browsers (ahem, IE), where
- // there isn't any inspectable "Arguments" type.
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return _.has(obj, 'callee');
- };
- }
-
- // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
- if (typeof /./ !== 'function') {
- _.isFunction = function(obj) {
- return typeof obj == 'function' || false;
- };
- }
-
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return isFinite(obj) && !isNaN(parseFloat(obj));
- };
-
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
- _.isNaN = function(obj) {
- return _.isNumber(obj) && obj !== +obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Shortcut function for checking if an object has a given property directly
- // on itself (in other words, not on a prototype).
- _.has = function(obj, key) {
- return obj != null && hasOwnProperty.call(obj, key);
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iteratees.
- _.identity = function(value) {
- return value;
- };
-
- // Predicate-generating functions. Often useful outside of Underscore.
- _.constant = function(value) {
- return function() {
- return value;
- };
- };
-
- _.noop = function(){};
-
- _.property = function(key) {
- return function(obj) {
- return obj[key];
- };
- };
-
- // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
- _.matches = function(attrs) {
- var pairs = _.pairs(attrs), length = pairs.length;
- return function(obj) {
- if (obj == null) return !length;
- obj = new Object(obj);
- for (var i = 0; i < length; i++) {
- var pair = pairs[i], key = pair[0];
- if (pair[1] !== obj[key] || !(key in obj)) return false;
- }
- return true;
- };
- };
-
- // Run a function **n** times.
- _.times = function(n, iteratee, context) {
- var accum = Array(Math.max(0, n));
- iteratee = createCallback(iteratee, context, 1);
- for (var i = 0; i < n; i++) accum[i] = iteratee(i);
- return accum;
- };
-
- // Return a random integer between min and max (inclusive).
- _.random = function(min, max) {
- if (max == null) {
- max = min;
- min = 0;
- }
- return min + Math.floor(Math.random() * (max - min + 1));
- };
-
- // A (possibly faster) way to get the current timestamp as an integer.
- _.now = Date.now || function() {
- return new Date().getTime();
- };
-
- // List of HTML entities for escaping.
- var escapeMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '`': '`'
- };
- var unescapeMap = _.invert(escapeMap);
-
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- var createEscaper = function(map) {
- var escaper = function(match) {
- return map[match];
- };
- // Regexes for identifying a key that needs to be escaped
- var source = '(?:' + _.keys(map).join('|') + ')';
- var testRegexp = RegExp(source);
- var replaceRegexp = RegExp(source, 'g');
- return function(string) {
- string = string == null ? '' : '' + string;
- return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
- };
- };
- _.escape = createEscaper(escapeMap);
- _.unescape = createEscaper(unescapeMap);
-
- // If the value of the named `property` is a function then invoke it with the
- // `object` as context; otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return void 0;
- var value = object[property];
- return _.isFunction(value) ? object[property]() : value;
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = ++idCounter + '';
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- };
-
- // When customizing `templateSettings`, if you don't want to define an
- // interpolation, evaluation or escaping regex, we need one that is
- // guaranteed not to match.
- var noMatch = /(.)^/;
-
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- "'": "'",
- '\\': '\\',
- '\r': 'r',
- '\n': 'n',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
-
- var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
-
- var escapeChar = function(match) {
- return '\\' + escapes[match];
- };
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- // NB: `oldSettings` only exists for backwards compatibility.
- _.template = function(text, settings, oldSettings) {
- if (!settings && oldSettings) settings = oldSettings;
- settings = _.defaults({}, settings, _.templateSettings);
-
- // Combine delimiters into one regular expression via alternation.
- var matcher = RegExp([
- (settings.escape || noMatch).source,
- (settings.interpolate || noMatch).source,
- (settings.evaluate || noMatch).source
- ].join('|') + '|$', 'g');
-
- // Compile the template source, escaping string literals appropriately.
- var index = 0;
- var source = "__p+='";
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset).replace(escaper, escapeChar);
- index = offset + match.length;
-
- if (escape) {
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- } else if (interpolate) {
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- } else if (evaluate) {
- source += "';\n" + evaluate + "\n__p+='";
- }
-
- // Adobe VMs need the match returned to produce the correct offest.
- return match;
- });
- source += "';\n";
-
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __t,__p='',__j=Array.prototype.join," +
- "print=function(){__p+=__j.call(arguments,'');};\n" +
- source + 'return __p;\n';
-
- try {
- var render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
-
- var template = function(data) {
- return render.call(this, data, _);
- };
-
- // Provide the compiled source as a convenience for precompilation.
- var argument = settings.variable || 'obj';
- template.source = 'function(' + argument + '){\n' + source + '}';
-
- return template;
- };
-
- // Add a "chain" function. Start chaining a wrapped Underscore object.
- _.chain = function(obj) {
- var instance = _(obj);
- instance._chain = true;
- return instance;
- };
-
- // OOP
- // ---------------
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj) {
- return this._chain ? _(obj).chain() : obj;
- };
-
- // Add your own custom functions to the Underscore object.
- _.mixin = function(obj) {
- _.each(_.functions(obj), function(name) {
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
- });
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- var obj = this._wrapped;
- method.apply(obj, arguments);
- if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
- return result.call(this, obj);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- _.each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- return result.call(this, method.apply(this._wrapped, arguments));
- };
- });
-
- // Extracts the result from a wrapped and chained object.
- _.prototype.value = function() {
- return this._wrapped;
- };
-
- // AMD registration happens at the end for compatibility with AMD loaders
- // that may not enforce next-turn semantics on modules. Even though general
- // practice for AMD registration is to be anonymous, underscore registers
- // as a named module because, like jQuery, it is a base library that is
- // popular enough to be bundled in a third party lib, but not be part of
- // an AMD load request. Those cases could generate an error when an
- // anonymous define() is called outside of a loader request.
- if (typeof define === 'function' && define.amd) {
- define('underscore', [], function() {
- return _;
- });
- }
-}.call(this));
\ No newline at end of file
[11/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/backgrid-0.3.5.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/backgrid-0.3.5.js b/htrace-htraced/src/web/lib/js/backgrid-0.3.5.js
deleted file mode 100644
index 6f8da79..0000000
--- a/htrace-htraced/src/web/lib/js/backgrid-0.3.5.js
+++ /dev/null
@@ -1,2883 +0,0 @@
-/*!
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2014 Jimmy Yuen Ho Wong and contributors <wy...@gmail.com>
- Licensed under the MIT license.
-*/
-
-(function (factory) {
-
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(module.exports,
- require("underscore"),
- require("backbone"));
- }
- // Browser
- else factory(this, this._, this.Backbone);
-}(function (root, _, Backbone) {
-
- "use strict";
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-// Copyright 2009, 2010 Kristopher Michael Kowal
-// https://github.com/kriskowal/es5-shim
-// ES5 15.5.4.20
-// http://es5.github.com/#x15.5.4.20
-var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
- "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
- "\u2029\uFEFF";
-if (!String.prototype.trim || ws.trim()) {
- // http://blog.stevenlevithan.com/archives/faster-trim-javascript
- // http://perfectionkills.com/whitespace-deviations/
- ws = "[" + ws + "]";
- var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
- trimEndRegexp = new RegExp(ws + ws + "*$");
- String.prototype.trim = function trim() {
- if (this === undefined || this === null) {
- throw new TypeError("can't convert " + this + " to object");
- }
- return String(this)
- .replace(trimBeginRegexp, "")
- .replace(trimEndRegexp, "");
- };
-}
-
-function lpad(str, length, padstr) {
- var paddingLen = length - (str + '').length;
- paddingLen = paddingLen < 0 ? 0 : paddingLen;
- var padding = '';
- for (var i = 0; i < paddingLen; i++) {
- padding = padding + padstr;
- }
- return padding + str;
-}
-
-var $ = Backbone.$;
-
-var Backgrid = root.Backgrid = {
-
- Extension: {},
-
- resolveNameToClass: function (name, suffix) {
- if (_.isString(name)) {
- var key = _.map(name.split('-'), function (e) {
- return e.slice(0, 1).toUpperCase() + e.slice(1);
- }).join('') + suffix;
- var klass = Backgrid[key] || Backgrid.Extension[key];
- if (_.isUndefined(klass)) {
- throw new ReferenceError("Class '" + key + "' not found");
- }
- return klass;
- }
-
- return name;
- },
-
- callByNeed: function () {
- var value = arguments[0];
- if (!_.isFunction(value)) return value;
-
- var context = arguments[1];
- var args = [].slice.call(arguments, 2);
- return value.apply(context, !!(args + '') ? args : []);
- }
-
-};
-_.extend(Backgrid, Backbone.Events);
-
-/**
- Command translates a DOM Event into commands that Backgrid
- recognizes. Interested parties can listen on selected Backgrid events that
- come with an instance of this class and act on the commands.
-
- It is also possible to globally rebind the keyboard shortcuts by replacing
- the methods in this class' prototype.
-
- @class Backgrid.Command
- @constructor
- */
-var Command = Backgrid.Command = function (evt) {
- _.extend(this, {
- altKey: !!evt.altKey,
- "char": evt["char"],
- charCode: evt.charCode,
- ctrlKey: !!evt.ctrlKey,
- key: evt.key,
- keyCode: evt.keyCode,
- locale: evt.locale,
- location: evt.location,
- metaKey: !!evt.metaKey,
- repeat: !!evt.repeat,
- shiftKey: !!evt.shiftKey,
- which: evt.which
- });
-};
-_.extend(Command.prototype, {
- /**
- Up Arrow
-
- @member Backgrid.Command
- */
- moveUp: function () { return this.keyCode == 38; },
- /**
- Down Arrow
-
- @member Backgrid.Command
- */
- moveDown: function () { return this.keyCode === 40; },
- /**
- Shift Tab
-
- @member Backgrid.Command
- */
- moveLeft: function () { return this.shiftKey && this.keyCode === 9; },
- /**
- Tab
-
- @member Backgrid.Command
- */
- moveRight: function () { return !this.shiftKey && this.keyCode === 9; },
- /**
- Enter
-
- @member Backgrid.Command
- */
- save: function () { return this.keyCode === 13; },
- /**
- Esc
-
- @member Backgrid.Command
- */
- cancel: function () { return this.keyCode === 27; },
- /**
- None of the above.
-
- @member Backgrid.Command
- */
- passThru: function () {
- return !(this.moveUp() || this.moveDown() || this.moveLeft() ||
- this.moveRight() || this.save() || this.cancel());
- }
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- Just a convenient class for interested parties to subclass.
-
- The default Cell classes don't require the formatter to be a subclass of
- Formatter as long as the fromRaw(rawData) and toRaw(formattedData) methods
- are defined.
-
- @abstract
- @class Backgrid.CellFormatter
- @constructor
-*/
-var CellFormatter = Backgrid.CellFormatter = function () {};
-_.extend(CellFormatter.prototype, {
-
- /**
- Takes a raw value from a model and returns an optionally formatted string
- for display. The default implementation simply returns the supplied value
- as is without any type conversion.
-
- @member Backgrid.CellFormatter
- @param {*} rawData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {*}
- */
- fromRaw: function (rawData, model) {
- return rawData;
- },
-
- /**
- Takes a formatted string, usually from user input, and returns a
- appropriately typed value for persistence in the model.
-
- If the user input is invalid or unable to be converted to a raw value
- suitable for persistence in the model, toRaw must return `undefined`.
-
- @member Backgrid.CellFormatter
- @param {string} formattedData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {*|undefined}
- */
- toRaw: function (formattedData, model) {
- return formattedData;
- }
-
-});
-
-/**
- A floating point number formatter. Doesn't understand scientific notation at
- the moment.
-
- @class Backgrid.NumberFormatter
- @extends Backgrid.CellFormatter
- @constructor
- @throws {RangeError} If decimals < 0 or > 20.
-*/
-var NumberFormatter = Backgrid.NumberFormatter = function (options) {
- _.extend(this, this.defaults, options || {});
-
- if (this.decimals < 0 || this.decimals > 20) {
- throw new RangeError("decimals must be between 0 and 20");
- }
-};
-NumberFormatter.prototype = new CellFormatter();
-_.extend(NumberFormatter.prototype, {
-
- /**
- @member Backgrid.NumberFormatter
- @cfg {Object} options
-
- @cfg {number} [options.decimals=2] Number of decimals to display. Must be an integer.
-
- @cfg {string} [options.decimalSeparator='.'] The separator to use when
- displaying decimals.
-
- @cfg {string} [options.orderSeparator=','] The separator to use to
- separator thousands. May be an empty string.
- */
- defaults: {
- decimals: 2,
- decimalSeparator: '.',
- orderSeparator: ','
- },
-
- HUMANIZED_NUM_RE: /(\d)(?=(?:\d{3})+$)/g,
-
- /**
- Takes a floating point number and convert it to a formatted string where
- every thousand is separated by `orderSeparator`, with a `decimal` number of
- decimals separated by `decimalSeparator`. The number returned is rounded
- the usual way.
-
- @member Backgrid.NumberFormatter
- @param {number} number
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string}
- */
- fromRaw: function (number, model) {
- if (_.isNull(number) || _.isUndefined(number)) return '';
-
- number = number.toFixed(~~this.decimals);
-
- var parts = number.split('.');
- var integerPart = parts[0];
- var decimalPart = parts[1] ? (this.decimalSeparator || '.') + parts[1] : '';
-
- return integerPart.replace(this.HUMANIZED_NUM_RE, '$1' + this.orderSeparator) + decimalPart;
- },
-
- /**
- Takes a string, possibly formatted with `orderSeparator` and/or
- `decimalSeparator`, and convert it back to a number.
-
- @member Backgrid.NumberFormatter
- @param {string} formattedData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {number|undefined} Undefined if the string cannot be converted to
- a number.
- */
- toRaw: function (formattedData, model) {
- formattedData = formattedData.trim();
-
- if (formattedData === '') return null;
-
- var rawData = '';
-
- var thousands = formattedData.split(this.orderSeparator);
- for (var i = 0; i < thousands.length; i++) {
- rawData += thousands[i];
- }
-
- var decimalParts = rawData.split(this.decimalSeparator);
- rawData = '';
- for (var i = 0; i < decimalParts.length; i++) {
- rawData = rawData + decimalParts[i] + '.';
- }
-
- if (rawData[rawData.length - 1] === '.') {
- rawData = rawData.slice(0, rawData.length - 1);
- }
-
- var result = (rawData * 1).toFixed(~~this.decimals) * 1;
- if (_.isNumber(result) && !_.isNaN(result)) return result;
- }
-
-});
-
-/**
- A number formatter that converts a floating point number, optionally
- multiplied by a multiplier, to a percentage string and vice versa.
-
- @class Backgrid.PercentFormatter
- @extends Backgrid.NumberFormatter
- @constructor
- @throws {RangeError} If decimals < 0 or > 20.
- */
-var PercentFormatter = Backgrid.PercentFormatter = function () {
- Backgrid.NumberFormatter.apply(this, arguments);
-};
-
-PercentFormatter.prototype = new Backgrid.NumberFormatter(),
-
-_.extend(PercentFormatter.prototype, {
-
- /**
- @member Backgrid.PercentFormatter
- @cfg {Object} options
-
- @cfg {number} [options.multiplier=1] The number used to multiply the model
- value for display.
-
- @cfg {string} [options.symbol='%'] The symbol to append to the percentage
- string.
- */
- defaults: _.extend({}, NumberFormatter.prototype.defaults, {
- multiplier: 1,
- symbol: "%"
- }),
-
- /**
- Takes a floating point number, where the number is first multiplied by
- `multiplier`, then converted to a formatted string like
- NumberFormatter#fromRaw, then finally append `symbol` to the end.
-
- @member Backgrid.PercentFormatter
- @param {number} rawValue
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string}
- */
- fromRaw: function (number, model) {
- var args = [].slice.call(arguments, 1);
- args.unshift(number * this.multiplier);
- return (NumberFormatter.prototype.fromRaw.apply(this, args) || "0") + this.symbol;
- },
-
- /**
- Takes a string, possibly appended with `symbol` and/or `decimalSeparator`,
- and convert it back to a number for the model like NumberFormatter#toRaw,
- and then dividing it by `multiplier`.
-
- @member Backgrid.PercentFormatter
- @param {string} formattedData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {number|undefined} Undefined if the string cannot be converted to
- a number.
- */
- toRaw: function (formattedValue, model) {
- var tokens = formattedValue.split(this.symbol);
- if (tokens && tokens[0] && tokens[1] === "" || tokens[1] == null) {
- var rawValue = NumberFormatter.prototype.toRaw.call(this, tokens[0]);
- if (_.isUndefined(rawValue)) return rawValue;
- return rawValue / this.multiplier;
- }
- }
-
-});
-
-/**
- Formatter to converts between various datetime formats.
-
- This class only understands ISO-8601 formatted datetime strings and UNIX
- offset (number of milliseconds since UNIX Epoch). See
- Backgrid.Extension.MomentFormatter if you need a much more flexible datetime
- formatter.
-
- @class Backgrid.DatetimeFormatter
- @extends Backgrid.CellFormatter
- @constructor
- @throws {Error} If both `includeDate` and `includeTime` are false.
-*/
-var DatetimeFormatter = Backgrid.DatetimeFormatter = function (options) {
- _.extend(this, this.defaults, options || {});
-
- if (!this.includeDate && !this.includeTime) {
- throw new Error("Either includeDate or includeTime must be true");
- }
-};
-DatetimeFormatter.prototype = new CellFormatter();
-_.extend(DatetimeFormatter.prototype, {
-
- /**
- @member Backgrid.DatetimeFormatter
-
- @cfg {Object} options
-
- @cfg {boolean} [options.includeDate=true] Whether the values include the
- date part.
-
- @cfg {boolean} [options.includeTime=true] Whether the values include the
- time part.
-
- @cfg {boolean} [options.includeMilli=false] If `includeTime` is true,
- whether to include the millisecond part, if it exists.
- */
- defaults: {
- includeDate: true,
- includeTime: true,
- includeMilli: false
- },
-
- DATE_RE: /^([+\-]?\d{4})-(\d{2})-(\d{2})$/,
- TIME_RE: /^(\d{2}):(\d{2}):(\d{2})(\.(\d{3}))?$/,
- ISO_SPLITTER_RE: /T|Z| +/,
-
- _convert: function (data, validate) {
- if ((data + '').trim() === '') return null;
-
- var date, time = null;
- if (_.isNumber(data)) {
- var jsDate = new Date(data);
- date = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
- time = lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
- }
- else {
- data = data.trim();
- var parts = data.split(this.ISO_SPLITTER_RE) || [];
- date = this.DATE_RE.test(parts[0]) ? parts[0] : '';
- time = date && parts[1] ? parts[1] : this.TIME_RE.test(parts[0]) ? parts[0] : '';
- }
-
- var YYYYMMDD = this.DATE_RE.exec(date) || [];
- var HHmmssSSS = this.TIME_RE.exec(time) || [];
-
- if (validate) {
- if (this.includeDate && _.isUndefined(YYYYMMDD[0])) return;
- if (this.includeTime && _.isUndefined(HHmmssSSS[0])) return;
- if (!this.includeDate && date) return;
- if (!this.includeTime && time) return;
- }
-
- var jsDate = new Date(Date.UTC(YYYYMMDD[1] * 1 || 0,
- YYYYMMDD[2] * 1 - 1 || 0,
- YYYYMMDD[3] * 1 || 0,
- HHmmssSSS[1] * 1 || null,
- HHmmssSSS[2] * 1 || null,
- HHmmssSSS[3] * 1 || null,
- HHmmssSSS[5] * 1 || null));
-
- var result = '';
-
- if (this.includeDate) {
- result = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
- }
-
- if (this.includeTime) {
- result = result + (this.includeDate ? 'T' : '') + lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
-
- if (this.includeMilli) {
- result = result + '.' + lpad(jsDate.getUTCMilliseconds(), 3, 0);
- }
- }
-
- if (this.includeDate && this.includeTime) {
- result += "Z";
- }
-
- return result;
- },
-
- /**
- Converts an ISO-8601 formatted datetime string to a datetime string, date
- string or a time string. The timezone is ignored if supplied.
-
- @member Backgrid.DatetimeFormatter
- @param {string} rawData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string|null|undefined} ISO-8601 string in UTC. Null and undefined
- values are returned as is.
- */
- fromRaw: function (rawData, model) {
- if (_.isNull(rawData) || _.isUndefined(rawData)) return '';
- return this._convert(rawData);
- },
-
- /**
- Converts an ISO-8601 formatted datetime string to a datetime string, date
- string or a time string. The timezone is ignored if supplied. This method
- parses the input values exactly the same way as
- Backgrid.Extension.MomentFormatter#fromRaw(), in addition to doing some
- sanity checks.
-
- @member Backgrid.DatetimeFormatter
- @param {string} formattedData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string|undefined} ISO-8601 string in UTC. Undefined if a date is
- found when `includeDate` is false, or a time is found when `includeTime` is
- false, or if `includeDate` is true and a date is not found, or if
- `includeTime` is true and a time is not found.
- */
- toRaw: function (formattedData, model) {
- return this._convert(formattedData, true);
- }
-
-});
-
-/**
- Formatter to convert any value to string.
-
- @class Backgrid.StringFormatter
- @extends Backgrid.CellFormatter
- @constructor
- */
-var StringFormatter = Backgrid.StringFormatter = function () {};
-StringFormatter.prototype = new CellFormatter();
-_.extend(StringFormatter.prototype, {
- /**
- Converts any value to a string using Ecmascript's implicit type
- conversion. If the given value is `null` or `undefined`, an empty string is
- returned instead.
-
- @member Backgrid.StringFormatter
- @param {*} rawValue
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string}
- */
- fromRaw: function (rawValue, model) {
- if (_.isUndefined(rawValue) || _.isNull(rawValue)) return '';
- return rawValue + '';
- }
-});
-
-/**
- Simple email validation formatter.
-
- @class Backgrid.EmailFormatter
- @extends Backgrid.CellFormatter
- @constructor
- */
-var EmailFormatter = Backgrid.EmailFormatter = function () {};
-EmailFormatter.prototype = new CellFormatter();
-_.extend(EmailFormatter.prototype, {
- /**
- Return the input if it is a string that contains an '@' character and if
- the strings before and after '@' are non-empty. If the input does not
- validate, `undefined` is returned.
-
- @member Backgrid.EmailFormatter
- @param {*} formattedData
- @param {Backbone.Model} model Used for more complicated formatting
- @return {string|undefined}
- */
- toRaw: function (formattedData, model) {
- var parts = formattedData.trim().split("@");
- if (parts.length === 2 && _.all(parts)) {
- return formattedData;
- }
- }
-});
-
-/**
- Formatter for SelectCell.
-
- If the type of a model value is not a string, it is expected that a subclass
- of this formatter is provided to the SelectCell, with #toRaw overridden to
- convert the string value returned from the DOM back to whatever value is
- expected in the model.
-
- @class Backgrid.SelectFormatter
- @extends Backgrid.CellFormatter
- @constructor
-*/
-var SelectFormatter = Backgrid.SelectFormatter = function () {};
-SelectFormatter.prototype = new CellFormatter();
-_.extend(SelectFormatter.prototype, {
-
- /**
- Normalizes raw scalar or array values to an array.
-
- @member Backgrid.SelectFormatter
- @param {*} rawValue
- @param {Backbone.Model} model Used for more complicated formatting
- @return {Array.<*>}
- */
- fromRaw: function (rawValue, model) {
- return _.isArray(rawValue) ? rawValue : rawValue != null ? [rawValue] : [];
- }
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- Generic cell editor base class. Only defines an initializer for a number of
- required parameters.
-
- @abstract
- @class Backgrid.CellEditor
- @extends Backbone.View
-*/
-var CellEditor = Backgrid.CellEditor = Backbone.View.extend({
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backgrid.CellFormatter} options.formatter
- @param {Backgrid.Column} options.column
- @param {Backbone.Model} options.model
-
- @throws {TypeError} If `formatter` is not a formatter instance, or when
- `model` or `column` are undefined.
- */
- initialize: function (options) {
- this.formatter = options.formatter;
- this.column = options.column;
- if (!(this.column instanceof Column)) {
- this.column = new Column(this.column);
- }
-
- this.listenTo(this.model, "backgrid:editing", this.postRender);
- },
-
- /**
- Post-rendering setup and initialization. Focuses the cell editor's `el` in
- this default implementation. **Should** be called by Cell classes after
- calling Backgrid.CellEditor#render.
- */
- postRender: function (model, column) {
- if (column == null || column.get("name") == this.column.get("name")) {
- this.$el.focus();
- }
- return this;
- }
-
-});
-
-/**
- InputCellEditor the cell editor type used by most core cell types. This cell
- editor renders a text input box as its editor. The input will render a
- placeholder if the value is empty on supported browsers.
-
- @class Backgrid.InputCellEditor
- @extends Backgrid.CellEditor
-*/
-var InputCellEditor = Backgrid.InputCellEditor = CellEditor.extend({
-
- /** @property */
- tagName: "input",
-
- /** @property */
- attributes: {
- type: "text"
- },
-
- /** @property */
- events: {
- "blur": "saveOrCancel",
- "keydown": "saveOrCancel"
- },
-
- /**
- Initializer. Removes this `el` from the DOM when a `done` event is
- triggered.
-
- @param {Object} options
- @param {Backgrid.CellFormatter} options.formatter
- @param {Backgrid.Column} options.column
- @param {Backbone.Model} options.model
- @param {string} [options.placeholder]
- */
- initialize: function (options) {
- InputCellEditor.__super__.initialize.apply(this, arguments);
-
- if (options.placeholder) {
- this.$el.attr("placeholder", options.placeholder);
- }
- },
-
- /**
- Renders a text input with the cell value formatted for display, if it
- exists.
- */
- render: function () {
- var model = this.model;
- this.$el.val(this.formatter.fromRaw(model.get(this.column.get("name")), model));
- return this;
- },
-
- /**
- If the key pressed is `enter`, `tab`, `up`, or `down`, converts the value
- in the editor to a raw value for saving into the model using the formatter.
-
- If the key pressed is `esc` the changes are undone.
-
- If the editor goes out of focus (`blur`) but the value is invalid, the
- event is intercepted and cancelled so the cell remains in focus pending for
- further action. The changes are saved otherwise.
-
- Triggers a Backbone `backgrid:edited` event from the model when successful,
- and `backgrid:error` if the value cannot be converted. Classes listening to
- the `error` event, usually the Cell classes, should respond appropriately,
- usually by rendering some kind of error feedback.
-
- @param {Event} e
- */
- saveOrCancel: function (e) {
-
- var formatter = this.formatter;
- var model = this.model;
- var column = this.column;
-
- var command = new Command(e);
- var blurred = e.type === "blur";
-
- if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
- command.save() || blurred) {
-
- e.preventDefault();
- e.stopPropagation();
-
- var val = this.$el.val();
- var newValue = formatter.toRaw(val, model);
- if (_.isUndefined(newValue)) {
- model.trigger("backgrid:error", model, column, val);
- }
- else {
- model.set(column.get("name"), newValue);
- model.trigger("backgrid:edited", model, column, command);
- }
- }
- // esc
- else if (command.cancel()) {
- // undo
- e.stopPropagation();
- model.trigger("backgrid:edited", model, column, command);
- }
- },
-
- postRender: function (model, column) {
- if (column == null || column.get("name") == this.column.get("name")) {
- // move the cursor to the end on firefox if text is right aligned
- if (this.$el.css("text-align") === "right") {
- var val = this.$el.val();
- this.$el.focus().val(null).val(val);
- }
- else this.$el.focus();
- }
- return this;
- }
-
-});
-
-/**
- The super-class for all Cell types. By default, this class renders a plain
- table cell with the model value converted to a string using the
- formatter. The table cell is clickable, upon which the cell will go into
- editor mode, which is rendered by a Backgrid.InputCellEditor instance by
- default. Upon encountering any formatting errors, this class will add an
- `error` CSS class to the table cell.
-
- @abstract
- @class Backgrid.Cell
- @extends Backbone.View
-*/
-var Cell = Backgrid.Cell = Backbone.View.extend({
-
- /** @property */
- tagName: "td",
-
- /**
- @property {Backgrid.CellFormatter|Object|string} [formatter=CellFormatter]
- */
- formatter: CellFormatter,
-
- /**
- @property {Backgrid.CellEditor} [editor=Backgrid.InputCellEditor] The
- default editor for all cell instances of this class. This value must be a
- class, it will be automatically instantiated upon entering edit mode.
-
- See Backgrid.CellEditor
- */
- editor: InputCellEditor,
-
- /** @property */
- events: {
- "click": "enterEditMode"
- },
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Model} options.model
- @param {Backgrid.Column} options.column
-
- @throws {ReferenceError} If formatter is a string but a formatter class of
- said name cannot be found in the Backgrid module.
- */
- initialize: function (options) {
- this.column = options.column;
- if (!(this.column instanceof Column)) {
- this.column = new Column(this.column);
- }
-
- var column = this.column, model = this.model, $el = this.$el;
-
- var formatter = Backgrid.resolveNameToClass(column.get("formatter") ||
- this.formatter, "Formatter");
-
- if (!_.isFunction(formatter.fromRaw) && !_.isFunction(formatter.toRaw)) {
- formatter = new formatter();
- }
-
- this.formatter = formatter;
-
- this.editor = Backgrid.resolveNameToClass(this.editor, "CellEditor");
-
- this.listenTo(model, "change:" + column.get("name"), function () {
- if (!$el.hasClass("editor")) this.render();
- });
-
- this.listenTo(model, "backgrid:error", this.renderError);
-
- this.listenTo(column, "change:editable change:sortable change:renderable",
- function (column) {
- var changed = column.changedAttributes();
- for (var key in changed) {
- if (changed.hasOwnProperty(key)) {
- $el.toggleClass(key, changed[key]);
- }
- }
- });
-
- if (Backgrid.callByNeed(column.editable(), column, model)) $el.addClass("editable");
- if (Backgrid.callByNeed(column.sortable(), column, model)) $el.addClass("sortable");
- if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable");
- },
-
- /**
- Render a text string in a table cell. The text is converted from the
- model's raw value for this cell's column.
- */
- render: function () {
- this.$el.empty();
- var model = this.model;
- this.$el.text(this.formatter.fromRaw(model.get(this.column.get("name")), model));
- this.delegateEvents();
- return this;
- },
-
- /**
- If this column is editable, a new CellEditor instance is instantiated with
- its required parameters. An `editor` CSS class is added to the cell upon
- entering edit mode.
-
- This method triggers a Backbone `backgrid:edit` event from the model when
- the cell is entering edit mode and an editor instance has been constructed,
- but before it is rendered and inserted into the DOM. The cell and the
- constructed cell editor instance are sent as event parameters when this
- event is triggered.
-
- When this cell has finished switching to edit mode, a Backbone
- `backgrid:editing` event is triggered from the model. The cell and the
- constructed cell instance are also sent as parameters in the event.
-
- When the model triggers a `backgrid:error` event, it means the editor is
- unable to convert the current user input to an apprpriate value for the
- model's column, and an `error` CSS class is added to the cell accordingly.
- */
- enterEditMode: function () {
- var model = this.model;
- var column = this.column;
-
- var editable = Backgrid.callByNeed(column.editable(), column, model);
- if (editable) {
-
- this.currentEditor = new this.editor({
- column: this.column,
- model: this.model,
- formatter: this.formatter
- });
-
- model.trigger("backgrid:edit", model, column, this, this.currentEditor);
-
- // Need to redundantly undelegate events for Firefox
- this.undelegateEvents();
- this.$el.empty();
- this.$el.append(this.currentEditor.$el);
- this.currentEditor.render();
- this.$el.addClass("editor");
-
- model.trigger("backgrid:editing", model, column, this, this.currentEditor);
- }
- },
-
- /**
- Put an `error` CSS class on the table cell.
- */
- renderError: function (model, column) {
- if (column == null || column.get("name") == this.column.get("name")) {
- this.$el.addClass("error");
- }
- },
-
- /**
- Removes the editor and re-render in display mode.
- */
- exitEditMode: function () {
- this.$el.removeClass("error");
- this.currentEditor.remove();
- this.stopListening(this.currentEditor);
- delete this.currentEditor;
- this.$el.removeClass("editor");
- this.render();
- },
-
- /**
- Clean up this cell.
-
- @chainable
- */
- remove: function () {
- if (this.currentEditor) {
- this.currentEditor.remove.apply(this.currentEditor, arguments);
- delete this.currentEditor;
- }
- return Cell.__super__.remove.apply(this, arguments);
- }
-
-});
-
-/**
- StringCell displays HTML escaped strings and accepts anything typed in.
-
- @class Backgrid.StringCell
- @extends Backgrid.Cell
-*/
-var StringCell = Backgrid.StringCell = Cell.extend({
-
- /** @property */
- className: "string-cell",
-
- formatter: StringFormatter
-
-});
-
-/**
- UriCell renders an HTML `<a>` anchor for the value and accepts URIs as user
- input values. No type conversion or URL validation is done by the formatter
- of this cell. Users who need URL validation are encourage to subclass UriCell
- to take advantage of the parsing capabilities of the HTMLAnchorElement
- available on HTML5-capable browsers or using a third-party library like
- [URI.js](https://github.com/medialize/URI.js).
-
- @class Backgrid.UriCell
- @extends Backgrid.Cell
-*/
-var UriCell = Backgrid.UriCell = Cell.extend({
-
- /** @property */
- className: "uri-cell",
-
- /**
- @property {string} [title] The title attribute of the generated anchor. It
- uses the display value formatted by the `formatter.fromRaw` by default.
- */
- title: null,
-
- /**
- @property {string} [target="_blank"] The target attribute of the generated
- anchor.
- */
- target: "_blank",
-
- initialize: function (options) {
- UriCell.__super__.initialize.apply(this, arguments);
- this.title = options.title || this.title;
- this.target = options.target || this.target;
- },
-
- render: function () {
- this.$el.empty();
- var rawValue = this.model.get(this.column.get("name"));
- var formattedValue = this.formatter.fromRaw(rawValue, this.model);
- this.$el.append($("<a>", {
- tabIndex: -1,
- href: rawValue,
- title: this.title || formattedValue,
- target: this.target
- }).text(formattedValue));
- this.delegateEvents();
- return this;
- }
-
-});
-
-/**
- Like Backgrid.UriCell, EmailCell renders an HTML `<a>` anchor for the
- value. The `href` in the anchor is prefixed with `mailto:`. EmailCell will
- complain if the user enters a string that doesn't contain the `@` sign.
-
- @class Backgrid.EmailCell
- @extends Backgrid.StringCell
-*/
-var EmailCell = Backgrid.EmailCell = StringCell.extend({
-
- /** @property */
- className: "email-cell",
-
- formatter: EmailFormatter,
-
- render: function () {
- this.$el.empty();
- var model = this.model;
- var formattedValue = this.formatter.fromRaw(model.get(this.column.get("name")), model);
- this.$el.append($("<a>", {
- tabIndex: -1,
- href: "mailto:" + formattedValue,
- title: formattedValue
- }).text(formattedValue));
- this.delegateEvents();
- return this;
- }
-
-});
-
-/**
- NumberCell is a generic cell that renders all numbers. Numbers are formatted
- using a Backgrid.NumberFormatter.
-
- @class Backgrid.NumberCell
- @extends Backgrid.Cell
-*/
-var NumberCell = Backgrid.NumberCell = Cell.extend({
-
- /** @property */
- className: "number-cell",
-
- /**
- @property {number} [decimals=2] Must be an integer.
- */
- decimals: NumberFormatter.prototype.defaults.decimals,
-
- /** @property {string} [decimalSeparator='.'] */
- decimalSeparator: NumberFormatter.prototype.defaults.decimalSeparator,
-
- /** @property {string} [orderSeparator=','] */
- orderSeparator: NumberFormatter.prototype.defaults.orderSeparator,
-
- /** @property {Backgrid.CellFormatter} [formatter=Backgrid.NumberFormatter] */
- formatter: NumberFormatter,
-
- /**
- Initializes this cell and the number formatter.
-
- @param {Object} options
- @param {Backbone.Model} options.model
- @param {Backgrid.Column} options.column
- */
- initialize: function (options) {
- NumberCell.__super__.initialize.apply(this, arguments);
- var formatter = this.formatter;
- formatter.decimals = this.decimals;
- formatter.decimalSeparator = this.decimalSeparator;
- formatter.orderSeparator = this.orderSeparator;
- }
-
-});
-
-/**
- An IntegerCell is just a Backgrid.NumberCell with 0 decimals. If a floating
- point number is supplied, the number is simply rounded the usual way when
- displayed.
-
- @class Backgrid.IntegerCell
- @extends Backgrid.NumberCell
-*/
-var IntegerCell = Backgrid.IntegerCell = NumberCell.extend({
-
- /** @property */
- className: "integer-cell",
-
- /**
- @property {number} decimals Must be an integer.
- */
- decimals: 0
-});
-
-/**
- A PercentCell is another Backgrid.NumberCell that takes a floating number,
- optionally multiplied by a multiplier and display it as a percentage.
-
- @class Backgrid.PercentCell
- @extends Backgrid.NumberCell
- */
-var PercentCell = Backgrid.PercentCell = NumberCell.extend({
-
- /** @property */
- className: "percent-cell",
-
- /** @property {number} [multiplier=1] */
- multiplier: PercentFormatter.prototype.defaults.multiplier,
-
- /** @property {string} [symbol='%'] */
- symbol: PercentFormatter.prototype.defaults.symbol,
-
- /** @property {Backgrid.CellFormatter} [formatter=Backgrid.PercentFormatter] */
- formatter: PercentFormatter,
-
- /**
- Initializes this cell and the percent formatter.
-
- @param {Object} options
- @param {Backbone.Model} options.model
- @param {Backgrid.Column} options.column
- */
- initialize: function () {
- PercentCell.__super__.initialize.apply(this, arguments);
- var formatter = this.formatter;
- formatter.multiplier = this.multiplier;
- formatter.symbol = this.symbol;
- }
-
-});
-
-/**
- DatetimeCell is a basic cell that accepts datetime string values in RFC-2822
- or W3C's subset of ISO-8601 and displays them in ISO-8601 format. For a much
- more sophisticated date time cell with better datetime formatting, take a
- look at the Backgrid.Extension.MomentCell extension.
-
- @class Backgrid.DatetimeCell
- @extends Backgrid.Cell
-
- See:
-
- - Backgrid.Extension.MomentCell
- - Backgrid.DatetimeFormatter
-*/
-var DatetimeCell = Backgrid.DatetimeCell = Cell.extend({
-
- /** @property */
- className: "datetime-cell",
-
- /**
- @property {boolean} [includeDate=true]
- */
- includeDate: DatetimeFormatter.prototype.defaults.includeDate,
-
- /**
- @property {boolean} [includeTime=true]
- */
- includeTime: DatetimeFormatter.prototype.defaults.includeTime,
-
- /**
- @property {boolean} [includeMilli=false]
- */
- includeMilli: DatetimeFormatter.prototype.defaults.includeMilli,
-
- /** @property {Backgrid.CellFormatter} [formatter=Backgrid.DatetimeFormatter] */
- formatter: DatetimeFormatter,
-
- /**
- Initializes this cell and the datetime formatter.
-
- @param {Object} options
- @param {Backbone.Model} options.model
- @param {Backgrid.Column} options.column
- */
- initialize: function (options) {
- DatetimeCell.__super__.initialize.apply(this, arguments);
- var formatter = this.formatter;
- formatter.includeDate = this.includeDate;
- formatter.includeTime = this.includeTime;
- formatter.includeMilli = this.includeMilli;
-
- var placeholder = this.includeDate ? "YYYY-MM-DD" : "";
- placeholder += (this.includeDate && this.includeTime) ? "T" : "";
- placeholder += this.includeTime ? "HH:mm:ss" : "";
- placeholder += (this.includeTime && this.includeMilli) ? ".SSS" : "";
-
- this.editor = this.editor.extend({
- attributes: _.extend({}, this.editor.prototype.attributes, this.editor.attributes, {
- placeholder: placeholder
- })
- });
- }
-
-});
-
-/**
- DateCell is a Backgrid.DatetimeCell without the time part.
-
- @class Backgrid.DateCell
- @extends Backgrid.DatetimeCell
-*/
-var DateCell = Backgrid.DateCell = DatetimeCell.extend({
-
- /** @property */
- className: "date-cell",
-
- /** @property */
- includeTime: false
-
-});
-
-/**
- TimeCell is a Backgrid.DatetimeCell without the date part.
-
- @class Backgrid.TimeCell
- @extends Backgrid.DatetimeCell
-*/
-var TimeCell = Backgrid.TimeCell = DatetimeCell.extend({
-
- /** @property */
- className: "time-cell",
-
- /** @property */
- includeDate: false
-
-});
-
-/**
- BooleanCellEditor renders a checkbox as its editor.
-
- @class Backgrid.BooleanCellEditor
- @extends Backgrid.CellEditor
-*/
-var BooleanCellEditor = Backgrid.BooleanCellEditor = CellEditor.extend({
-
- /** @property */
- tagName: "input",
-
- /** @property */
- attributes: {
- tabIndex: -1,
- type: "checkbox"
- },
-
- /** @property */
- events: {
- "mousedown": function () {
- this.mouseDown = true;
- },
- "blur": "enterOrExitEditMode",
- "mouseup": function () {
- this.mouseDown = false;
- },
- "change": "saveOrCancel",
- "keydown": "saveOrCancel"
- },
-
- /**
- Renders a checkbox and check it if the model value of this column is true,
- uncheck otherwise.
- */
- render: function () {
- var model = this.model;
- var val = this.formatter.fromRaw(model.get(this.column.get("name")), model);
- this.$el.prop("checked", val);
- return this;
- },
-
- /**
- Event handler. Hack to deal with the case where `blur` is fired before
- `change` and `click` on a checkbox.
- */
- enterOrExitEditMode: function (e) {
- if (!this.mouseDown) {
- var model = this.model;
- model.trigger("backgrid:edited", model, this.column, new Command(e));
- }
- },
-
- /**
- Event handler. Save the value into the model if the event is `change` or
- one of the keyboard navigation key presses. Exit edit mode without saving
- if `escape` was pressed.
- */
- saveOrCancel: function (e) {
- var model = this.model;
- var column = this.column;
- var formatter = this.formatter;
- var command = new Command(e);
- // skip ahead to `change` when space is pressed
- if (command.passThru() && e.type != "change") return true;
- if (command.cancel()) {
- e.stopPropagation();
- model.trigger("backgrid:edited", model, column, command);
- }
-
- var $el = this.$el;
- if (command.save() || command.moveLeft() || command.moveRight() || command.moveUp() ||
- command.moveDown()) {
- e.preventDefault();
- e.stopPropagation();
- var val = formatter.toRaw($el.prop("checked"), model);
- model.set(column.get("name"), val);
- model.trigger("backgrid:edited", model, column, command);
- }
- else if (e.type == "change") {
- var val = formatter.toRaw($el.prop("checked"), model);
- model.set(column.get("name"), val);
- $el.focus();
- }
- }
-
-});
-
-/**
- BooleanCell renders a checkbox both during display mode and edit mode. The
- checkbox is checked if the model value is true, unchecked otherwise.
-
- @class Backgrid.BooleanCell
- @extends Backgrid.Cell
-*/
-var BooleanCell = Backgrid.BooleanCell = Cell.extend({
-
- /** @property */
- className: "boolean-cell",
-
- /** @property */
- editor: BooleanCellEditor,
-
- /** @property */
- events: {
- "click": "enterEditMode"
- },
-
- /**
- Renders a checkbox and check it if the model value of this column is true,
- uncheck otherwise.
- */
- render: function () {
- this.$el.empty();
- var model = this.model, column = this.column;
- var editable = Backgrid.callByNeed(column.editable(), column, model);
- this.$el.append($("<input>", {
- tabIndex: -1,
- type: "checkbox",
- checked: this.formatter.fromRaw(model.get(column.get("name")), model),
- disabled: !editable
- }));
- this.delegateEvents();
- return this;
- }
-
-});
-
-/**
- SelectCellEditor renders an HTML `<select>` fragment as the editor.
-
- @class Backgrid.SelectCellEditor
- @extends Backgrid.CellEditor
-*/
-var SelectCellEditor = Backgrid.SelectCellEditor = CellEditor.extend({
-
- /** @property */
- tagName: "select",
-
- /** @property */
- events: {
- "change": "save",
- "blur": "close",
- "keydown": "close"
- },
-
- /** @property {function(Object, ?Object=): string} template */
- template: _.template('<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>', null, {variable: null}),
-
- setOptionValues: function (optionValues) {
- this.optionValues = optionValues;
- this.optionValues = _.result(this, "optionValues");
- },
-
- setMultiple: function (multiple) {
- this.multiple = multiple;
- this.$el.prop("multiple", multiple);
- },
-
- _renderOptions: function (nvps, selectedValues) {
- var options = '';
- for (var i = 0; i < nvps.length; i++) {
- options = options + this.template({
- text: nvps[i][0],
- value: nvps[i][1],
- selected: _.indexOf(selectedValues, nvps[i][1]) > -1
- });
- }
- return options;
- },
-
- /**
- Renders the options if `optionValues` is a list of name-value pairs. The
- options are contained inside option groups if `optionValues` is a list of
- object hashes. The name is rendered at the option text and the value is the
- option value. If `optionValues` is a function, it is called without a
- parameter.
- */
- render: function () {
- this.$el.empty();
-
- var optionValues = _.result(this, "optionValues");
- var model = this.model;
- var selectedValues = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-
- if (!_.isArray(optionValues)) throw new TypeError("optionValues must be an array");
-
- var optionValue = null;
- var optionText = null;
- var optionValue = null;
- var optgroupName = null;
- var optgroup = null;
-
- for (var i = 0; i < optionValues.length; i++) {
- var optionValue = optionValues[i];
-
- if (_.isArray(optionValue)) {
- optionText = optionValue[0];
- optionValue = optionValue[1];
-
- this.$el.append(this.template({
- text: optionText,
- value: optionValue,
- selected: _.indexOf(selectedValues, optionValue) > -1
- }));
- }
- else if (_.isObject(optionValue)) {
- optgroupName = optionValue.name;
- optgroup = $("<optgroup></optgroup>", { label: optgroupName });
- optgroup.append(this._renderOptions.call(this, optionValue.values, selectedValues));
- this.$el.append(optgroup);
- }
- else {
- throw new TypeError("optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }");
- }
- }
-
- this.delegateEvents();
-
- return this;
- },
-
- /**
- Saves the value of the selected option to the model attribute.
- */
- save: function (e) {
- var model = this.model;
- var column = this.column;
- model.set(column.get("name"), this.formatter.toRaw(this.$el.val(), model));
- },
-
- /**
- Triggers a `backgrid:edited` event from the model so the body can close
- this editor.
- */
- close: function (e) {
- var model = this.model;
- var column = this.column;
- var command = new Command(e);
- if (command.cancel()) {
- e.stopPropagation();
- model.trigger("backgrid:edited", model, column, new Command(e));
- }
- else if (command.save() || command.moveLeft() || command.moveRight() ||
- command.moveUp() || command.moveDown() || e.type == "blur") {
- e.preventDefault();
- e.stopPropagation();
- this.save(e);
- model.trigger("backgrid:edited", model, column, new Command(e));
- }
- }
-
-});
-
-/**
- SelectCell is also a different kind of cell in that upon going into edit mode
- the cell renders a list of options to pick from, as opposed to an input box.
-
- SelectCell cannot be referenced by its string name when used in a column
- definition because it requires an `optionValues` class attribute to be
- defined. `optionValues` can either be a list of name-value pairs, to be
- rendered as options, or a list of object hashes which consist of a key *name*
- which is the option group name, and a key *values* which is a list of
- name-value pairs to be rendered as options under that option group.
-
- In addition, `optionValues` can also be a parameter-less function that
- returns one of the above. If the options are static, it is recommended the
- returned values to be memoized. `_.memoize()` is a good function to help with
- that.
-
- During display mode, the default formatter will normalize the raw model value
- to an array of values whether the raw model value is a scalar or an
- array. Each value is compared with the `optionValues` values using
- Ecmascript's implicit type conversion rules. When exiting edit mode, no type
- conversion is performed when saving into the model. This behavior is not
- always desirable when the value type is anything other than string. To
- control type conversion on the client-side, you should subclass SelectCell to
- provide a custom formatter or provide the formatter to your column
- definition.
-
- See:
- [$.fn.val()](http://api.jquery.com/val/)
-
- @class Backgrid.SelectCell
- @extends Backgrid.Cell
-*/
-var SelectCell = Backgrid.SelectCell = Cell.extend({
-
- /** @property */
- className: "select-cell",
-
- /** @property */
- editor: SelectCellEditor,
-
- /** @property */
- multiple: false,
-
- /** @property */
- formatter: SelectFormatter,
-
- /**
- @property {Array.<Array>|Array.<{name: string, values: Array.<Array>}>} optionValues
- */
- optionValues: undefined,
-
- /** @property */
- delimiter: ', ',
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Model} options.model
- @param {Backgrid.Column} options.column
-
- @throws {TypeError} If `optionsValues` is undefined.
- */
- initialize: function (options) {
- SelectCell.__super__.initialize.apply(this, arguments);
- this.listenTo(this.model, "backgrid:edit", function (model, column, cell, editor) {
- if (column.get("name") == this.column.get("name")) {
- editor.setOptionValues(this.optionValues);
- editor.setMultiple(this.multiple);
- }
- });
- },
-
- /**
- Renders the label using the raw value as key to look up from `optionValues`.
-
- @throws {TypeError} If `optionValues` is malformed.
- */
- render: function () {
- this.$el.empty();
-
- var optionValues = _.result(this, "optionValues");
- var model = this.model;
- var rawData = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-
- var selectedText = [];
-
- try {
- if (!_.isArray(optionValues) || _.isEmpty(optionValues)) throw new TypeError;
-
- for (var k = 0; k < rawData.length; k++) {
- var rawDatum = rawData[k];
-
- for (var i = 0; i < optionValues.length; i++) {
- var optionValue = optionValues[i];
-
- if (_.isArray(optionValue)) {
- var optionText = optionValue[0];
- var optionValue = optionValue[1];
-
- if (optionValue == rawDatum) selectedText.push(optionText);
- }
- else if (_.isObject(optionValue)) {
- var optionGroupValues = optionValue.values;
-
- for (var j = 0; j < optionGroupValues.length; j++) {
- var optionGroupValue = optionGroupValues[j];
- if (optionGroupValue[1] == rawDatum) {
- selectedText.push(optionGroupValue[0]);
- }
- }
- }
- else {
- throw new TypeError;
- }
- }
- }
-
- this.$el.append(selectedText.join(this.delimiter));
- }
- catch (ex) {
- if (ex instanceof TypeError) {
- throw new TypeError("'optionValues' must be of type {Array.<Array>|Array.<{name: string, values: Array.<Array>}>}");
- }
- throw ex;
- }
-
- this.delegateEvents();
-
- return this;
- }
-
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- A Column is a placeholder for column metadata.
-
- You usually don't need to create an instance of this class yourself as a
- collection of column instances will be created for you from a list of column
- attributes in the Backgrid.js view class constructors.
-
- @class Backgrid.Column
- @extends Backbone.Model
-*/
-var Column = Backgrid.Column = Backbone.Model.extend({
-
- /**
- @cfg {Object} defaults Column defaults. To override any of these default
- values, you can either change the prototype directly to override
- Column.defaults globally or extend Column and supply the custom class to
- Backgrid.Grid:
-
- // Override Column defaults globally
- Column.prototype.defaults.sortable = false;
-
- // Override Column defaults locally
- var MyColumn = Column.extend({
- defaults: _.defaults({
- editable: false
- }, Column.prototype.defaults)
- });
-
- var grid = new Backgrid.Grid(columns: new Columns([{...}, {...}], {
- model: MyColumn
- }));
-
- @cfg {string} [defaults.name] The default name of the model attribute.
-
- @cfg {string} [defaults.label] The default label to show in the header.
-
- @cfg {string|Backgrid.Cell} [defaults.cell] The default cell type. If this
- is a string, the capitalized form will be used to look up a cell class in
- Backbone, i.e.: string => StringCell. If a Cell subclass is supplied, it is
- initialized with a hash of parameters. If a Cell instance is supplied, it
- is used directly.
-
- @cfg {string|Backgrid.HeaderCell} [defaults.headerCell] The default header
- cell type.
-
- @cfg {boolean|string|function(): boolean} [defaults.sortable=true] Whether
- this column is sortable. If the value is a string, a method will the same
- name will be looked up from the column instance to determine whether the
- column should be sortable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
-
- @cfg {boolean|string|function(): boolean} [defaults.editable=true] Whether
- this column is editable. If the value is a string, a method will the same
- name will be looked up from the column instance to determine whether the
- column should be editable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
-
- @cfg {boolean|string|function(): boolean} [defaults.renderable=true]
- Whether this column is renderable. If the value is a string, a method will
- the same name will be looked up from the column instance to determine
- whether the column should be renderable. The method's signature must be
- `function (Backrid.Column, Backbone.Model): boolean`.
-
- @cfg {Backgrid.CellFormatter | Object | string} [defaults.formatter] The
- formatter to use to convert between raw model values and user input.
-
- @cfg {"toggle"|"cycle"} [defaults.sortType="cycle"] Whether sorting will
- toggle between ascending and descending order, or cycle between insertion
- order, ascending and descending order.
-
- @cfg {(function(Backbone.Model, string): *) | string} [defaults.sortValue]
- The function to use to extract a value from the model for comparison during
- sorting. If this value is a string, a method with the same name will be
- looked up from the column instance.
-
- @cfg {"ascending"|"descending"|null} [defaults.direction=null] The initial
- sorting direction for this column. The default is ordered by
- Backbone.Model.cid, which usually means the collection is ordered by
- insertion order.
- */
- defaults: {
- name: undefined,
- label: undefined,
- sortable: true,
- editable: true,
- renderable: true,
- formatter: undefined,
- sortType: "cycle",
- sortValue: undefined,
- direction: null,
- cell: undefined,
- headerCell: undefined
- },
-
- /**
- Initializes this Column instance.
-
- @param {Object} attrs
-
- @param {string} attrs.name The model attribute this column is responsible
- for.
-
- @param {string|Backgrid.Cell} attrs.cell The cell type to use to render
- this column.
-
- @param {string} [attrs.label]
-
- @param {string|Backgrid.HeaderCell} [attrs.headerCell]
-
- @param {boolean|string|function(): boolean} [attrs.sortable=true]
-
- @param {boolean|string|function(): boolean} [attrs.editable=true]
-
- @param {boolean|string|function(): boolean} [attrs.renderable=true]
-
- @param {Backgrid.CellFormatter | Object | string} [attrs.formatter]
-
- @param {"toggle"|"cycle"} [attrs.sortType="cycle"]
-
- @param {(function(Backbone.Model, string): *) | string} [attrs.sortValue]
-
- @throws {TypeError} If attrs.cell or attrs.options are not supplied.
-
- @throws {ReferenceError} If formatter is a string but a formatter class of
- said name cannot be found in the Backgrid module.
-
- See:
-
- - Backgrid.Column.defaults
- - Backgrid.Cell
- - Backgrid.CellFormatter
- */
- initialize: function () {
- if (!this.has("label")) {
- this.set({ label: this.get("name") }, { silent: true });
- }
-
- var headerCell = Backgrid.resolveNameToClass(this.get("headerCell"), "HeaderCell");
-
- var cell = Backgrid.resolveNameToClass(this.get("cell"), "Cell");
-
- this.set({cell: cell, headerCell: headerCell}, { silent: true });
- },
-
- /**
- Returns an appropriate value extraction function from a model for sorting.
-
- If the column model contains an attribute `sortValue`, if it is a string, a
- method from the column instance identifified by the `sortValue` string is
- returned. If it is a function, it it returned as is. If `sortValue` isn't
- found from the column model's attributes, a default value extraction
- function is returned which will compare according to the natural order of
- the value's type.
-
- @return {function(Backbone.Model, string): *}
- */
- sortValue: function () {
- var sortValue = this.get("sortValue");
- if (_.isString(sortValue)) return this[sortValue];
- else if (_.isFunction(sortValue)) return sortValue;
-
- return function (model, colName) {
- return model.get(colName);
- };
- }
-
- /**
- @member Backgrid.Column
- @protected
- @method sortable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
- */
-
- /**
- @member Backgrid.Column
- @protected
- @method editable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
- */
-
- /**
- @member Backgrid.Column
- @protected
- @method renderable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
- */
-});
-
-_.each(["sortable", "renderable", "editable"], function (key) {
- Column.prototype[key] = function () {
- var value = this.get(key);
- if (_.isString(value)) return this[value];
- else if (_.isFunction(value)) return value;
-
- return !!value;
- };
-});
-
-/**
- A Backbone collection of Column instances.
-
- @class Backgrid.Columns
- @extends Backbone.Collection
- */
-var Columns = Backgrid.Columns = Backbone.Collection.extend({
-
- /**
- @property {Backgrid.Column} model
- */
- model: Column
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- Row is a simple container view that takes a model instance and a list of
- column metadata describing how each of the model's attribute is to be
- rendered, and apply the appropriate cell to each attribute.
-
- @class Backgrid.Row
- @extends Backbone.View
-*/
-var Row = Backgrid.Row = Backbone.View.extend({
-
- /** @property */
- tagName: "tr",
-
- /**
- Initializes a row view instance.
-
- @param {Object} options
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
- @param {Backbone.Model} options.model The model instance to render.
-
- @throws {TypeError} If options.columns or options.model is undefined.
- */
- initialize: function (options) {
-
- var columns = this.columns = options.columns;
- if (!(columns instanceof Backbone.Collection)) {
- columns = this.columns = new Columns(columns);
- }
-
- var cells = this.cells = [];
- for (var i = 0; i < columns.length; i++) {
- cells.push(this.makeCell(columns.at(i), options));
- }
-
- this.listenTo(columns, "add", function (column, columns) {
- var i = columns.indexOf(column);
- var cell = this.makeCell(column, options);
- cells.splice(i, 0, cell);
-
- var $el = this.$el;
- if (i === 0) {
- $el.prepend(cell.render().$el);
- }
- else if (i === columns.length - 1) {
- $el.append(cell.render().$el);
- }
- else {
- $el.children().eq(i).before(cell.render().$el);
- }
- });
-
- this.listenTo(columns, "remove", function (column, columns, opts) {
- cells[opts.index].remove();
- cells.splice(opts.index, 1);
- });
- },
-
- /**
- Factory method for making a cell. Used by #initialize internally. Override
- this to provide an appropriate cell instance for a custom Row subclass.
-
- @protected
-
- @param {Backgrid.Column} column
- @param {Object} options The options passed to #initialize.
-
- @return {Backgrid.Cell}
- */
- makeCell: function (column) {
- return new (column.get("cell"))({
- column: column,
- model: this.model
- });
- },
-
- /**
- Renders a row of cells for this row's model.
- */
- render: function () {
- this.$el.empty();
-
- var fragment = document.createDocumentFragment();
- for (var i = 0; i < this.cells.length; i++) {
- fragment.appendChild(this.cells[i].render().el);
- }
-
- this.el.appendChild(fragment);
-
- this.delegateEvents();
-
- return this;
- },
-
- /**
- Clean up this row and its cells.
-
- @chainable
- */
- remove: function () {
- for (var i = 0; i < this.cells.length; i++) {
- var cell = this.cells[i];
- cell.remove.apply(cell, arguments);
- }
- return Backbone.View.prototype.remove.apply(this, arguments);
- }
-
-});
-
-/**
- EmptyRow is a simple container view that takes a list of column and render a
- row with a single column.
-
- @class Backgrid.EmptyRow
- @extends Backbone.View
-*/
-var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
-
- /** @property */
- tagName: "tr",
-
- /** @property {string|function(): string} */
- emptyText: null,
-
- /**
- Initializer.
-
- @param {Object} options
- @param {string|function(): string} options.emptyText
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
- */
- initialize: function (options) {
- this.emptyText = options.emptyText;
- this.columns = options.columns;
- },
-
- /**
- Renders an empty row.
- */
- render: function () {
- this.$el.empty();
-
- var td = document.createElement("td");
- td.setAttribute("colspan", this.columns.length);
- td.appendChild(document.createTextNode(_.result(this, "emptyText")));
-
- this.el.className = "empty";
- this.el.appendChild(td);
-
- return this;
- }
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- HeaderCell is a special cell class that renders a column header cell. If the
- column is sortable, a sorter is also rendered and will trigger a table
- refresh after sorting.
-
- @class Backgrid.HeaderCell
- @extends Backbone.View
- */
-var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
-
- /** @property */
- tagName: "th",
-
- /** @property */
- events: {
- "click a": "onClick"
- },
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backgrid.Column|Object} options.column
-
- @throws {TypeError} If options.column or options.collection is undefined.
- */
- initialize: function (options) {
- this.column = options.column;
- if (!(this.column instanceof Column)) {
- this.column = new Column(this.column);
- }
-
- var column = this.column, collection = this.collection, $el = this.$el;
-
- this.listenTo(column, "change:editable change:sortable change:renderable",
- function (column) {
- var changed = column.changedAttributes();
- for (var key in changed) {
- if (changed.hasOwnProperty(key)) {
- $el.toggleClass(key, changed[key]);
- }
- }
- });
- this.listenTo(column, "change:direction", this.setCellDirection);
- this.listenTo(column, "change:name change:label", this.render);
-
- if (Backgrid.callByNeed(column.editable(), column, collection)) $el.addClass("editable");
- if (Backgrid.callByNeed(column.sortable(), column, collection)) $el.addClass("sortable");
- if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
-
- this.listenTo(collection.fullCollection || collection, "sort", this.removeCellDirection);
- },
-
- /**
- Event handler for the collection's `sort` event. Removes all the CSS
- direction classes.
- */
- removeCellDirection: function () {
- this.$el.removeClass("ascending").removeClass("descending");
- this.column.set("direction", null);
- },
-
- /**
- Event handler for the column's `change:direction` event. If this
- HeaderCell's column is being sorted on, it applies the direction given as a
- CSS class to the header cell. Removes all the CSS direction classes
- otherwise.
- */
- setCellDirection: function (column, direction) {
- this.$el.removeClass("ascending").removeClass("descending");
- if (column.cid == this.column.cid) this.$el.addClass(direction);
- },
-
- /**
- Event handler for the `click` event on the cell's anchor. If the column is
- sortable, clicking on the anchor will cycle through 3 sorting orderings -
- `ascending`, `descending`, and default.
- */
- onClick: function (e) {
- e.preventDefault();
-
- var column = this.column;
- var collection = this.collection;
- var event = "backgrid:sort";
-
- function cycleSort(header, col) {
- if (column.get("direction") === "ascending") collection.trigger(event, col, "descending");
- else if (column.get("direction") === "descending") collection.trigger(event, col, null);
- else collection.trigger(event, col, "ascending");
- }
-
- function toggleSort(header, col) {
- if (column.get("direction") === "ascending") collection.trigger(event, col, "descending");
- else collection.trigger(event, col, "ascending");
- }
-
- var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
- if (sortable) {
- var sortType = column.get("sortType");
- if (sortType === "toggle") toggleSort(this, column);
- else cycleSort(this, column);
- }
- },
-
- /**
- Renders a header cell with a sorter, a label, and a class name for this
- column.
- */
- render: function () {
- this.$el.empty();
- var column = this.column;
- var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
- var label;
- if(sortable){
- label = $("<a>").text(column.get("label")).append("<b class='sort-caret'></b>");
- } else {
- label = document.createTextNode(column.get("label"));
- }
-
- this.$el.append(label);
- this.$el.addClass(column.get("name"));
- this.$el.addClass(column.get("direction"));
- this.delegateEvents();
- return this;
- }
-
-});
-
-/**
- HeaderRow is a controller for a row of header cells.
-
- @class Backgrid.HeaderRow
- @extends Backgrid.Row
- */
-var HeaderRow = Backgrid.HeaderRow = Backgrid.Row.extend({
-
- requiredOptions: ["columns", "collection"],
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
- @param {Backgrid.HeaderCell} [options.headerCell] Customized default
- HeaderCell for all the columns. Supply a HeaderCell class or instance to a
- the `headerCell` key in a column definition for column-specific header
- rendering.
-
- @throws {TypeError} If options.columns or options.collection is undefined.
- */
- initialize: function () {
- Backgrid.Row.prototype.initialize.apply(this, arguments);
- },
-
- makeCell: function (column, options) {
- var headerCell = column.get("headerCell") || options.headerCell || HeaderCell;
- headerCell = new headerCell({
- column: column,
- collection: this.collection
- });
- return headerCell;
- }
-
-});
-
-/**
- Header is a special structural view class that renders a table head with a
- single row of header cells.
-
- @class Backgrid.Header
- @extends Backbone.View
- */
-var Header = Backgrid.Header = Backbone.View.extend({
-
- /** @property */
- tagName: "thead",
-
- /**
- Initializer. Initializes this table head view to contain a single header
- row view.
-
- @param {Object} options
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
- @param {Backbone.Model} options.model The model instance to render.
-
- @throws {TypeError} If options.columns or options.model is undefined.
- */
- initialize: function (options) {
- this.columns = options.columns;
- if (!(this.columns instanceof Backbone.Collection)) {
- this.columns = new Columns(this.columns);
- }
-
- this.row = new Backgrid.HeaderRow({
- columns: this.columns,
- collection: this.collection
- });
- },
-
- /**
- Renders this table head with a single row of header cells.
- */
- render: function () {
- this.$el.append(this.row.render().$el);
- this.delegateEvents();
- return this;
- },
-
- /**
- Clean up this header and its row.
-
- @chainable
- */
- remove: function () {
- this.row.remove.apply(this.row, arguments);
- return Backbone.View.prototype.remove.apply(this, arguments);
- }
-
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- Body is the table body which contains the rows inside a table. Body is
- responsible for refreshing the rows after sorting, insertion and removal.
-
- @class Backgrid.Body
- @extends Backbone.View
-*/
-var Body = Backgrid.Body = Backbone.View.extend({
-
- /** @property */
- tagName: "tbody",
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Collection} options.collection
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
- Column metadata.
- @param {Backgrid.Row} [options.row=Backgrid.Row] The Row class to use.
- @param {string|function(): string} [options.emptyText] The text to display in the empty row.
-
- @throws {TypeError} If options.columns or options.collection is undefined.
-
- See Backgrid.Row.
- */
- initialize: function (options) {
-
- this.columns = options.columns;
- if (!(this.columns instanceof Backbone.Collection)) {
- this.columns = new Columns(this.columns);
- }
-
- this.row = options.row || Row;
- this.rows = this.collection.map(function (model) {
- var row = new this.row({
- columns: this.columns,
- model: model
- });
-
- return row;
- }, this);
-
- this.emptyText = options.emptyText;
- this._unshiftEmptyRowMayBe();
-
- var collection = this.collection;
- this.listenTo(collection, "add", this.insertRow);
- this.listenTo(collection, "remove", this.removeRow);
- this.listenTo(collection, "sort", this.refresh);
- this.listenTo(collection, "reset", this.refresh);
- this.listenTo(collection, "backgrid:sort", this.sort);
- this.listenTo(collection, "backgrid:edited", this.moveToNextCell);
- },
-
- _unshiftEmptyRowMayBe: function () {
- if (this.rows.length === 0 && this.emptyText != null) {
- this.rows.unshift(new EmptyRow({
- emptyText: this.emptyText,
- columns: this.columns
- }));
- }
- },
-
- /**
- This method can be called either directly or as a callback to a
- [Backbone.Collecton#add](http://backbonejs.org/#Collection-add) event.
-
- When called directly, it accepts a model or an array of models and an
- option hash just like
- [Backbone.Collection#add](http://backbonejs.org/#Collection-add) and
- delegates to it. Once the model is added, a new row is inserted into the
- body and automatically rendered.
-
- When called as a callback of an `add` event, splices a new row into the
- body and renders it.
-
- @param {Backbone.Model} model The model to render as a row.
- @param {Backbone.Collection} collection When called directly, this
- parameter is actually the options to
- [Backbone.Collection#add](http://backbonejs.org/#Collection-add).
- @param {Object} options When called directly, this must be null.
-
- See:
-
- - [Backbone.Collection#add](http://backbonejs.org/#Collection-add)
- */
- insertRow: function (model, collection, options) {
-
- if (this.rows[0] instanceof EmptyRow) this.rows.pop().remove();
-
- // insertRow() is called directly
- if (!(collection instanceof Backbone.Collection) && !options) {
- this.collection.add(model, (options = collection));
- return;
- }
-
- var row = new this.row({
- columns: this.columns,
- model: model
- });
-
- var index = collection.indexOf(model);
- this.rows.splice(index, 0, row);
-
- var $el = this.$el;
- var $children = $el.children();
- var $rowEl = row.render().$el;
-
- if (index >= $children.length) {
- $el.append($rowEl);
- }
- else {
- $children.eq(index).before($rowEl);
- }
-
- return this;
- },
-
- /**
- The method can be called either directly or as a callback to a
- [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove)
- event.
-
- When called directly, it accepts a model or an array of models and an
- option hash just like
- [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove) and
- delegates to it. Once the model is removed, a corresponding row is removed
- from the body.
-
- When called as a callback of a `remove` event, splices into the rows and
- removes the row responsible for rendering the model.
-
- @param {Backbone.Model} model The model to remove from the body.
- @param {Backbone.Collection} collection When called directly, this
- parameter is actually the options to
- [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove).
- @param {Object} options When called directly, this must be null.
-
- See:
-
- - [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove)
- */
- removeRow: function (model, collection, options) {
-
- // removeRow() is called directly
- if (!options) {
- this.collection.remove(model, (options = collection));
- this._unshiftEmptyRowMayBe();
- return;
- }
-
- if (_.isUndefined(options.render) || options.render) {
- this.rows[options.index].remove();
- }
-
- this.rows.splice(options.index, 1);
- this._unshiftEmptyRowMayBe();
-
- return this;
- },
-
- /**
- Reinitialize all the rows inside the body and re-render them. Triggers a
- Backbone `backgrid:refresh` event from the collection along with the body
- instance as its sole parameter when done.
- */
- refresh: function () {
- for (var i = 0; i < this.rows.length; i++) {
- this.rows[i].remove();
- }
-
- this.rows = this.collection.map(function (model) {
- var row = new this.row({
- columns: this.columns,
- model: model
- });
-
- return row;
- }, this);
- this._unshiftEmptyRowMayBe();
-
- this.render();
-
- this.collection.trigger("backgrid:refresh", this);
-
- return this;
- },
-
- /**
- Renders all the rows inside this body. If the collection is empty and
- `options.emptyText` is defined and not null in the constructor, an empty
- row is rendered, otherwise no row is rendered.
- */
- render: function () {
- this.$el.empty();
-
- var fragment = document.createDocumentFragment();
- for (var i = 0; i < this.rows.length; i++) {
- var row = this.rows[i];
- fragment.appendChild(row.render().el);
- }
-
- this.el.appendChild(fragment);
-
- this.delegateEvents();
-
- return this;
- },
-
- /**
- Clean up this body and it's rows.
-
- @chainable
- */
- remove: function () {
- for (var i = 0; i < this.rows.length; i++) {
- var row = this.rows[i];
- row.remove.apply(row, arguments);
- }
- return Backbone.View.prototype.remove.apply(this, arguments);
- },
-
- /**
- If the underlying collection is a Backbone.PageableCollection in
- server-mode or infinite-mode, a page of models is fetched after sorting is
- done on the server.
-
- If the underlying collection is a Backbone.PageableCollection in
- client-mode, or any
- [Backbone.Collection](http://backbonejs.org/#Collection) instance, sorting
- is done on the client side. If the collection is an instance of a
- Backbone.PageableCollection, sorting will be done globally on all the pages
- and the current page will then be returned.
-
- Triggers a Backbone `backgrid:sorted` event from the collection when done
- with the column, direction and a reference to the collection.
-
- @param {Backgrid.Column} column
- @param {null|"ascending"|"descending"} direction
-
- See [Backbone.Collection#comparator](http://backbonejs.org/#Collection-comparator)
- */
- sort: function (column, direction) {
-
- if (!_.contains(["ascending", "descending", null], direction)) {
- throw new RangeError('direction must be one of "ascending", "descending" or `null`');
- }
-
- if (_.isString(column)) column = this.columns.findWhere({name: column});
-
- var collection = this.collection;
-
- var order;
- if (direction === "ascending") order = -1;
- else if (direction === "descending") order = 1;
- else order = null;
-
- var comparator = this.makeComparator(column.get("name"), order,
- order ?
- column.sortValue() :
- function (model) {
- return model.cid.replace('c', '') * 1;
- });
-
- if (Backbone.PageableCollection &&
- collection instanceof Backbone.PageableCollection) {
-
- collection.setSorting(order && column.get("name"), order,
- {sortValue: column.sortValue()});
-
- if (collection.fullCollection) {
- // If order is null, pageable will remove the comparator on both sides,
- // in this case the default insertion order comparator needs to be
- // attached to get back to the order before sorting.
- if (collection.fullCollection.comparator == null) {
- collection.fullCollection.comparator = comparator;
- }
- collection.fullCollection.sort();
- collection.trigger("backgrid:sorted", column, direction, collection);
- }
- else collection.fetch({reset: true, success: function () {
- collection.trigger("backgrid:sorted", column, direction, collection);
- }});
- }
- else {
- collection.comparator = comparator;
- collection.sort();
- collection.trigger("backgrid:sorted", column, direction, collection);
- }
-
- column.set("direction", direction);
-
- return this;
- },
-
- makeComparator: function (attr, order, func) {
-
- return function (left, right) {
- // extract the values from the models
- var l = func(left, attr), r = func(right, attr), t;
-
- // if descending order, swap left and right
- if (order === 1) t = l, l = r, r = t;
-
- // compare as usual
- if (l === r) return 0;
- else if (l < r) return -1;
- return 1;
- };
- },
-
- /**
- Moves focus to the next renderable and editable cell and return the
- currently editing cell to display mode.
-
- Triggers a `backgrid:next` event on the model with the indices of the row
- and column the user *intended* to move to, and whether the intended move
- was going to go out of bounds. Note that *out of bound* always means an
- attempt to go past the end of the last row.
-
- @param {Backbone.Model} model The originating model
- @param {Backgrid.Column} column The originating model column
- @param {Backgrid.Command} command The Command object constructed from a DOM
- event
- */
- moveToNextCell: function (model, column, command) {
- var i = this.collection.indexOf(model);
- var j = this.columns.indexOf(column);
- var cell, renderable, editable, m, n;
-
- this.rows[i].cells[j].exitEditMode();
-
- if (command.moveUp() || command.moveDown() || command.moveLeft() ||
- command.moveRight() || command.save()) {
- var l = this.columns.length;
- var maxOffset = l * this.collection.length;
-
- if (command.moveUp() || command.moveDown()) {
- m = i + (command.moveUp() ? -1 : 1);
- var row = this.rows[m];
- if (row) {
- cell = row.cells[j];
- if (Backgrid.callByNeed(cell.column.editable(), cell.column, model)) {
- cell.enterEditMode();
- model.trigger("backgrid:next", m, j, false);
- }
- }
- else model.trigger("backgrid:next", m, j, true);
- }
- else if (command.moveLeft() || command.moveRight()) {
- var right = command.moveRight();
- for (var offset = i * l + j + (right ? 1 : -1);
- offset >= 0 && offset < maxOffset;
- right ? offset++ : offset--) {
- m = ~~(offset / l);
- n = offset - m * l;
- cell = this.rows[m].cells[n];
- renderable = Backgrid.callByNeed(cell.column.renderable(), cell.column, cell.model);
- editable = Backgrid.callByNeed(cell.column.editable(), cell.column, model);
- if (renderable && editable) {
- cell.enterEditMode();
- model.trigger("backgrid:next", m, n, false);
- break;
- }
- }
-
- if (offset == maxOffset) {
- model.trigger("backgrid:next", ~~(offset / l), offset - m * l, true);
- }
- }
- }
-
- return this;
- }
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- A Footer is a generic class that only defines a default tag `tfoot` and
- number of required parameters in the initializer.
-
- @abstract
- @class Backgrid.Footer
- @extends Backbone.View
- */
-var Footer = Backgrid.Footer = Backbone.View.extend({
-
- /** @property */
- tagName: "tfoot",
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
- Column metadata.
- @param {Backbone.Collection} options.collection
-
- @throws {TypeError} If options.columns or options.collection is undefined.
- */
- initialize: function (options) {
- this.columns = options.columns;
- if (!(this.columns instanceof Backbone.Collection)) {
- this.columns = new Backgrid.Columns(this.columns);
- }
- }
-
-});
-
-/*
- backgrid
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT license.
-*/
-
-/**
- Grid represents a data grid that has a header, body and an optional footer.
-
- By default, a Grid treats each model in a collection as a row, and each
- attribute in a model as a column. To render a grid you must provide a list of
- column metadata and a collection to the Grid constructor. Just like any
- Backbone.View class, the grid is rendered as a DOM node fragment when you
- call render().
-
- var grid = Backgrid.Grid({
- columns: [{ name: "id", label: "ID", type: "string" },
- // ...
- ],
- collections: books
- });
-
- $("#table-container").append(grid.render().el);
-
- Optionally, if you want to customize the rendering of the grid's header and
- footer, you may choose to extend Backgrid.Header and Backgrid.Footer, and
- then supply that class or an instance of that class to the Grid constructor.
- See the documentation for Header and Footer for further details.
-
- var grid = Backgrid.Grid({
- columns: [{ name: "id", label: "ID", type: "string" }],
- collections: books,
- header: Backgrid.Header.extend({
- //...
- }),
- footer: Backgrid.Paginator
- });
-
- Finally, if you want to override how the rows are rendered in the table body,
- you can supply a Body subclass as the `body` attribute that uses a different
- Row class.
-
- @class Backgrid.Grid
- @extends Backbone.View
-
- See:
-
- - Backgrid.Column
- - Backgrid.Header
- - Backgrid.Body
- - Backgrid.Row
- - Backgrid.Footer
-*/
-var Grid = Backgrid.Grid = Backbone.View.extend({
-
- /** @property */
- tagName: "table",
-
- /** @property */
- className: "backgrid",
-
- /** @property */
- header: Header,
-
- /** @property */
- body: Body,
-
- /** @property */
- footer: null,
-
- /**
- Initializes a Grid instance.
-
- @param {Object} options
- @param {Backbone.Collection.<Backgrid.Columns>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
- @param {Backbone.Collection} options.collection The collection of tabular model data to display.
- @param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
- @param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
- @param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
- @param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class.
- */
- initialize: function (options) {
- // Convert the list of column objects here first so the subviews don't have
- // to.
- if (!(options.columns instanceof Backbone.Collection)) {
- options.columns = new Columns(options.columns);
- }
- this.columns = options.columns;
-
- var filteredOptions = _.omit(options, ["el", "id", "attributes",
- "className", "tagName", "events"]);
-
- // must construct body first so it listens to backgrid:sort first
- this.body = options.body || this.body;
- this.body = new this.body(filteredOptions);
-
- this.header = options.header || this.header;
- if (this.header) {
- this.header = new this.header(filteredOptions);
- }
-
- this.footer = options.footer || this.footer;
- if (this.footer) {
- this.footer = new this.footer(filteredOptions);
- }
-
- this.listenTo(this.columns, "reset", function () {
- if (this.header) {
- this.header = new (this.header.remove().constructor)(filteredOptions);
- }
- this.body = new (this.body.remove().constructor)(filteredOptions);
- if (this.footer) {
- this.footer = new (this.footer.remove().constructor)(filteredOptions);
- }
- this.render();
- });
- },
-
- /**
- Delegates to Backgrid.Body#insertRow.
- */
- insertRow: function () {
- this.body.insertRow.apply(this.body, arguments);
- return this;
- },
-
- /**
- Delegates to Backgrid.Body#removeRow.
- */
- removeRow: function () {
- this.body.removeRow.apply(this.body, arguments);
- return this;
- },
-
- /**
- Delegates to Backgrid.Columns#add for adding a column. Subviews can listen
- to the `add` event from their internal `columns` if rerendering needs to
- happen.
-
- @param {Object} [options] Options for `Backgrid.Columns#add`.
- */
- insertColumn: function () {
- this.columns.add.apply(this.columns, arguments);
- return this;
- },
-
- /**
- Delegates to Backgrid.Columns#remove for removing a column. Subviews can
- listen to the `remove` event from the internal `columns` if rerendering
- needs to happen.
-
- @param {Object} [options] Options for `Backgrid.Columns#remove`.
- */
- removeColumn: function () {
- this.columns.remove.apply(this.columns, arguments);
- return this;
- },
-
- /**
- Delegates to Backgrid.Body#sort.
- */
- sort: function () {
- this.body.sort.apply(this.body, arguments);
- return this;
- },
-
- /**
- Renders the grid's header, then footer, then finally the body. Triggers a
- Backbone `backgrid:rendered` event along with a reference to the grid when
- the it has successfully been rendered.
- */
- render: function () {
- this.$el.empty();
-
- if (this.header) {
- this.$el.append(this.header.render().$el);
- }
-
- if (this.footer) {
- this.$el.append(this.footer.render().$el);
- }
-
- this.$el.append(this.body.render().$el);
-
- this.delegateEvents();
-
- this.trigger("backgrid:rendered", this);
-
- return this;
- },
-
- /**
- Clean up this grid and its subviews.
-
- @chainable
- */
- remove: function () {
- this.header && this.header.remove.apply(this.header, arguments);
- this.body.remove.apply(this.body, arguments);
- this.footer && this.footer.remove.apply(this.footer, arguments);
- return Backbone.View.prototype.remove.apply(this, arguments);
- }
-
-});
-return Backgrid;
-}));
\ No newline at end of file
[08/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/jquery-2.1.3.min.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/jquery-2.1.3.min.js b/htrace-htraced/src/web/lib/js/jquery-2.1.3.min.js
deleted file mode 100644
index 25714ed..0000000
--- a/htrace-htraced/src/web/lib/js/jquery-2.1.3.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
-!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=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,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=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.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},n.extend=n.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||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:functi
on(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},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=s(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(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;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=s(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&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){va
r b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=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=hb(),z=hb(),A=hb(),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-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=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)},eb=function(){m()};try{H.apply(E=I.call(v.child
Nodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){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 gb(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(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(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 hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(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 mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(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 pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.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",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(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.parent
Node?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);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))&&(jb(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(".#.+[+~]")}),jb(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))&&jb(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 lb(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?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.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 gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.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},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.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=gb.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=gb.selectors={cacheLength:50,createPseudo:ib,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(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===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]||gb.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]&&gb.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(cb,db).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=gb.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()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(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:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(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:ib(function(a){return function(b){return gb(a,b).length>0}}),c
ontains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).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)r
eturn!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:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(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]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=n
ew qb,g=gb.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?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(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 tb(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 ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(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 wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(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=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(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=[sb(tb(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 wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(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=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f)
{b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.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(cb,db),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(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.fir
stChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(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}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);
b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jqu
ery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;r
eturn this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(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&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextS
ibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0
],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"re
solved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.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?n.extend(a,d):d}},e={};return d.pipe=d.then,n.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&&n.isFunction(a.promise)?e:0,g=1===f?a:n.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]&&n.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;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n
.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(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};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d
];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;retu
rn c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
-},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.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.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(
a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.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 L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.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=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l
,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)i
f(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.names
pace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j
=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!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(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return
h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},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 offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.
keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.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=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventL
istener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.
event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.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(g in a)this.on(g,b,c,a[g],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=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f
.guid||(f.guid=n.guid++)),this.each(function(){n.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,n(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=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead
:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}functi
on ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]
||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeTyp
e||9===this.nodeType){var b=jb(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=jb(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?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{}
,c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(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,n.cleanData(ob(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,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=
c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,
b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.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}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);f
unction g(){f.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",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.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 zb=/^(non
e|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(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+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.b
oxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.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}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(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":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks
[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.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))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRi
ght,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,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.en
d=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):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):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.
elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.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,n.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 Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=thi
s,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a)
.show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.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 Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),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:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Twe
en(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(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.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)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?
d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(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=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.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)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.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})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.
push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.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=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&
&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.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 n.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=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.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||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHo
oks[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){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},rem
oveClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.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(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(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(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.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&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.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){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.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 cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c
))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.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 sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(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.resp
onseFields[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}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,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":n.parseJSON,"text xml":n.parseXM
L},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e: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 c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.succ
ess=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentT
ype)&&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]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.d
ata,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,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElemen
tChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction
(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",fu
nction(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;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)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, appl
ication/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fc=[],Gc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCal
lback,h?b[h]=b[h].replace(Gc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.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,Fc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hc)return Hc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseH
TML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ic=a.document.documentElement;function Jc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.off
set.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ic;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ic})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jc(
b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.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?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kc=a.jQuery,Lc=a.$;return n.noConflict=function(
b){return a.$===n&&(a.$=Lc),b&&a.jQuery===n&&(a.jQuery=Kc),n},typeof b===U&&(a.jQuery=a.$=n),n});
[05/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.css b/htrace-htraced/src/web/lib/rome-2.1.0/rome.css
deleted file mode 100644
index 3c4c861..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.css
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * rome - Customizable date (and time) picker. Opt-in UI, no jQuery!
- * @version v2.1.0
- * @link https://github.com/bevacqua/rome
- * @license MIT
- */
-.rd-container {
- display: inline-block;
- border: 1px solid #333;
- background-color: #fff;
- padding: 10px;
- text-align: center;
-}
-.rd-container-attachment {
- position: absolute;
-}
-.rd-month {
- display: inline-block;
- margin-right: 25px;
-}
-.rd-month:last-child {
- margin-right: 0;
-}
-.rd-back,
-.rd-next {
- cursor: pointer;
- border: none;
- outline: none;
- background: none;
- padding: 0;
- margin: 0;
-}
-.rd-back[disabled],
-.rd-next[disabled] {
- cursor: default;
-}
-.rd-back {
- float: left;
-}
-.rd-next {
- float: right;
-}
-.rd-back:before {
- display: block;
- content: '\2190';
-}
-.rd-next:before {
- display: block;
- content: '\2192';
-}
-.rd-day-body {
- cursor: pointer;
- text-align: center;
-}
-.rd-day-selected,
-.rd-time-selected,
-.rd-time-option:hover {
- cursor: pointer;
- background-color: #333;
- color: #fff;
-}
-.rd-day-prev-month,
-.rd-day-next-month {
- color: #999;
-}
-.rd-day-disabled {
- cursor: default;
- color: #fcc;
-}
-.rd-time {
- position: relative;
- display: inline-block;
- margin-top: 5px;
- min-width: 80px;
-}
-.rd-time-list {
- display: none;
- position: absolute;
- overflow-y: scroll;
- max-height: 160px;
- left: 0;
- right: 0;
- background-color: #fff;
- color: #333;
-}
-.rd-time-selected {
- padding: 5px;
-}
-.rd-time-option {
- padding: 5px;
-}
-.rd-day-concealed {
- visibility: hidden;
-}
[03/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.css b/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.css
deleted file mode 100644
index 7967e65..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/* rome@v2.1.0, MIT licensed. https://github.com/bevacqua/rome */
-.rd-container{display:inline-block;border:1px solid #333;background-color:#fff;padding:10px;text-align:center}.rd-container-attachment{position:absolute}.rd-month{display:inline-block;margin-right:25px}.rd-month:last-child{margin-right:0}.rd-back,.rd-next{cursor:pointer;border:none;outline:0;background:0 0;padding:0;margin:0}.rd-back[disabled],.rd-next[disabled]{cursor:default}.rd-back{float:left}.rd-next{float:right}.rd-back:before{display:block;content:'\2190'}.rd-next:before{display:block;content:'\2192'}.rd-day-body{cursor:pointer;text-align:center}.rd-day-selected,.rd-time-option:hover,.rd-time-selected{cursor:pointer;background-color:#333;color:#fff}.rd-day-next-month,.rd-day-prev-month{color:#999}.rd-day-disabled{cursor:default;color:#fcc}.rd-time{position:relative;display:inline-block;margin-top:5px;min-width:80px}.rd-time-list{display:none;position:absolute;overflow-y:scroll;max-height:160px;left:0;right:0;background-color:#fff;color:#333}.rd-time-option,.rd-time-selected{p
adding:5px}.rd-day-concealed{visibility:hidden}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.js b/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.js
deleted file mode 100644
index 8514e04..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-// rome@v2.1.0, MIT licensed. https://github.com/bevacqua/rome
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.rome=t()}}(function(){var t;return function e(t,n,r){function a(o,s){if(!n[o]){if(!t[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var c=n[o]={exports:{}};t[o][0].call(c.exports,function(e){var n=t[o][1][e];return a(n?n:e)},c,c.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)a(r[o]);return a}({1:[function(t,e){function n(){}var r=e.exports={};r.nextTick=function(){var t="undefined"!=typeof window&&window.setImmediate,e="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(t)return function(t){return window.setImmediate(t)};if(e){var n=[];return window.addEven
tListener("message",function(t){var e=t.source;if((e===window||null===e)&&"process-tick"===t.data&&(t.stopPropagation(),n.length>0)){var r=n.shift();r()}},!0),function(t){n.push(t),window.postMessage("process-tick","*")}}return function(t){setTimeout(t,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.on=n,r.addListener=n,r.once=n,r.off=n,r.removeListener=n,r.removeAllListeners=n,r.emit=n,r.binding=function(){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(){throw new Error("process.chdir is not supported")}},{}],2:[function(t,e){e.exports=t("./src/contra.emitter.js")},{"./src/contra.emitter.js":3}],3:[function(t,e){(function(t){!function(n,r){"use strict";function a(t,e){return Array.prototype.slice.call(t,e)}function i(t,e,n){t&&s(function(){t.apply(n||null,e||[])})}function o(t,e){var n=e||{},o={};return t===r&&(t={}),t.on=function(e,n){return o[e]?o[e].push(n):o[e]=[n],t},t.once=function(e,n){return n._once=!0,t.on(e,n),
t},t.off=function(e,n){var r=arguments.length;if(1===r)delete o[e];else if(0===r)o={};else{var a=o[e];if(!a)return t;a.splice(a.indexOf(n),1)}return t},t.emit=function(){var e=a(arguments);return t.emitterSnapshot(e.shift()).apply(this,e)},t.emitterSnapshot=function(e){var r=(o[e]||[]).slice(0);return function(){var s=a(arguments),u=this||t;if("error"===e&&n.throws!==!1&&!r.length)throw 1===s.length?s[0]:s;return o[e]=r.filter(function(t){return n.async?i(t,s,u):t.apply(u,s),!t._once}),t}},t}var s,u=""+r,c="function"==typeof setImmediate;s=c?function(t){setImmediate(t)}:typeof t!==u&&t.nextTick?t.nextTick:function(t){setTimeout(t,0)},typeof e!==u&&e.exports?e.exports=o:(n.contra=n.contra||{},n.contra.emitter=o)}(this)}).call(this,t("FWaASH"))},{FWaASH:1}],4:[function(e,n){(function(r){(function(a){function i(t,e,n){switch(arguments.length){case 2:return null!=t?t:e;case 3:return null!=t?t:null!=e?e:n;default:throw new Error("Implement me")}}function o(t,e){return Oe.call(t,e)}functi
on s(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function u(t){De.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function c(t,e){var n=!0;return p(function(){return n&&(u(t),n=!1),e.apply(this,arguments)},e)}function l(t,e){bn[t]||(u(e),bn[t]=!0)}function d(t,e){return function(n){return g(t.call(this,n),e)}}function f(t,e){return function(n){return this.localeData().ordinal(t.call(this,n),e)}}function h(){}function m(t,e){e!==!1&&H(t),_(this,t),this._d=new Date(+t._d)}function y(t){var e=S(t),n=e.year||0,r=e.quarter||0,a=e.month||0,i=e.week||0,o=e.day||0,s=e.hour||0,u=e.minute||0,c=e.second||0,l=e.millisecond||0;this._milliseconds=+l+1e3*c+6e4*u+36e5*s,this._days=+o+7*i,this._months=+a+3*r+12*n,this._data={},this._locale=De.localeData(),this._bubble()}function p(t,e){for(var n in e)o(e,n)&&(t[n]=e[n]);retur
n o(e,"toString")&&(t.toString=e.toString),o(e,"valueOf")&&(t.valueOf=e.valueOf),t}function _(t,e){var n,r,a;if("undefined"!=typeof e._isAMomentObject&&(t._isAMomentObject=e._isAMomentObject),"undefined"!=typeof e._i&&(t._i=e._i),"undefined"!=typeof e._f&&(t._f=e._f),"undefined"!=typeof e._l&&(t._l=e._l),"undefined"!=typeof e._strict&&(t._strict=e._strict),"undefined"!=typeof e._tzm&&(t._tzm=e._tzm),"undefined"!=typeof e._isUTC&&(t._isUTC=e._isUTC),"undefined"!=typeof e._offset&&(t._offset=e._offset),"undefined"!=typeof e._pf&&(t._pf=e._pf),"undefined"!=typeof e._locale&&(t._locale=e._locale),Le.length>0)for(n in Le)r=Le[n],a=e[r],"undefined"!=typeof a&&(t[r]=a);return t}function v(t){return 0>t?Math.ceil(t):Math.floor(t)}function g(t,e,n){for(var r=""+Math.abs(t),a=t>=0;r.length<e;)r="0"+r;return(a?n?"+":"":"-")+r}function w(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.millisecon
ds=+e-+t.clone().add(n.months,"M"),n}function b(t,e){var n;return e=U(e,t),t.isBefore(e)?n=w(t,e):(n=w(e,t),n.milliseconds=-n.milliseconds,n.months=-n.months),n}function M(t,e){return function(n,r){var a,i;return null===r||isNaN(+r)||(l(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period)."),i=n,n=r,r=i),n="string"==typeof n?+n:n,a=De.duration(n,r),D(this,a,t),this}}function D(t,e,n,r){var a=e._milliseconds,i=e._days,o=e._months;r=null==r?!0:r,a&&t._d.setTime(+t._d+a*n),i&&_e(t,"Date",pe(t,"Date")+i*n),o&&ye(t,pe(t,"Month")+o*n),r&&De.updateOffset(t,i||o)}function k(t){return"[object Array]"===Object.prototype.toString.call(t)}function Y(t){return"[object Date]"===Object.prototype.toString.call(t)||t instanceof Date}function T(t,e,n){var r,a=Math.min(t.length,e.length),i=Math.abs(t.length-e.length),o=0;for(r=0;a>r;r++)(n&&t[r]!==e[r]||!n&&F(t[r])!==F(e[r]))&&o++;return o+i}function x(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=mn[t]||
yn[e]||e}return t}function S(t){var e,n,r={};for(n in t)o(t,n)&&(e=x(n),e&&(r[e]=t[n]));return r}function O(t){var e,n;if(0===t.indexOf("week"))e=7,n="day";else{if(0!==t.indexOf("month"))return;e=12,n="month"}De[t]=function(r,i){var o,s,u=De._locale[t],c=[];if("number"==typeof r&&(i=r,r=a),s=function(t){var e=De().utc().set(n,t);return u.call(De._locale,e,r||"")},null!=i)return s(i);for(o=0;e>o;o++)c.push(s(o));return c}}function F(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=e>=0?Math.floor(e):Math.ceil(e)),n}function C(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function I(t,e,n){return de(De([t,11,31+e-n]),e,n).week}function A(t){return E(t)?366:365}function E(t){return t%4===0&&t%100!==0||t%400===0}function H(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[Ce]<0||t._a[Ce]>11?Ce:t._a[Ie]<1||t._a[Ie]>C(t._a[Fe],t._a[Ce])?Ie:t._a[Ae]<0||t._a[Ae]>24||24===t._a[Ae]&&(0!==t._a[Ee]||0!==t._a[He]||0!==t._a[Pe])?Ae:t._a[Ee]<0||t._a[Ee]>59?Ee:t._a[He]<0||t._a[He]>59?He:t._a[Pe]<0||t
._a[Pe]>999?Pe:-1,t._pf._overflowDayOfYear&&(Fe>e||e>Ie)&&(e=Ie),t._pf.overflow=e)}function P(t){return null==t._isValid&&(t._isValid=!isNaN(t._d.getTime())&&t._pf.overflow<0&&!t._pf.empty&&!t._pf.invalidMonth&&!t._pf.nullInput&&!t._pf.invalidFormat&&!t._pf.userInvalidated,t._strict&&(t._isValid=t._isValid&&0===t._pf.charsLeftOver&&0===t._pf.unusedTokens.length&&t._pf.bigHour===a)),t._isValid}function W(t){return t?t.toLowerCase().replace("_","-"):t}function L(t){for(var e,n,r,a,i=0;i<t.length;){for(a=W(t[i]).split("-"),e=a.length,n=W(t[i+1]),n=n?n.split("-"):null;e>0;){if(r=G(a.slice(0,e).join("-")))return r;if(n&&n.length>=e&&T(a,n,!0)>=e-1)break;e--}i++}return null}function G(t){var n=null;if(!We[t]&&Ge)try{n=De.locale(),e("./locale/"+t),De.locale(n)}catch(r){}return We[t]}function U(t,e){var n,r;return e._isUTC?(n=e.clone(),r=(De.isMoment(t)||Y(t)?+t:+De(t))-+n,n._d.setTime(+n._d+r),De.updateOffset(n,!1),n):De(t).local()}function N(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]
$/g,""):t.replace(/\\/g,"")}function z(t){var e,n,r=t.match(je);for(e=0,n=r.length;n>e;e++)r[e]=wn[r[e]]?wn[r[e]]:N(r[e]);return function(a){var i="";for(e=0;n>e;e++)i+=r[e]instanceof Function?r[e].call(a,t):r[e];return i}}function j(t,e){return t.isValid()?(e=V(e,t.localeData()),pn[e]||(pn[e]=z(e)),pn[e](t)):t.localeData().invalidDate()}function V(t,e){function n(t){return e.longDateFormat(t)||t}var r=5;for(Ve.lastIndex=0;r>=0&&Ve.test(t);)t=t.replace(Ve,n),Ve.lastIndex=0,r-=1;return t}function B(t,e){var n,r=e._strict;switch(t){case"Q":return en;case"DDDD":return rn;case"YYYY":case"GGGG":case"gggg":return r?an:qe;case"Y":case"G":case"g":return sn;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return r?on:Re;case"S":if(r)return en;case"SS":if(r)return nn;case"SSS":if(r)return rn;case"DDD":return Ze;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Je;case"a":case"A":return e._locale._meridiemParse;case"x":return Ke;case"X":return tn;case"Z":case"ZZ":return Qe;case"T":retu
rn Xe;case"SSSS":return $e;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return r?nn:Be;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Be;case"Do":return r?e._locale._ordinalParse:e._locale._ordinalParseLenient;default:return n=new RegExp(te(K(t.replace("\\","")),"i"))}}function Z(t){t=t||"";var e=t.match(Qe)||[],n=e[e.length-1]||[],r=(n+"").match(fn)||["-",0,0],a=+(60*r[1])+F(r[2]);return"+"===r[0]?-a:a}function q(t,e,n){var r,a=n._a;switch(t){case"Q":null!=e&&(a[Ce]=3*(F(e)-1));break;case"M":case"MM":null!=e&&(a[Ce]=F(e)-1);break;case"MMM":case"MMMM":r=n._locale.monthsParse(e,t,n._strict),null!=r?a[Ce]=r:n._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(a[Ie]=F(e));break;case"Do":null!=e&&(a[Ie]=F(parseInt(e.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=e&&(n._dayOfYear=F(e));break;case"YY":a[Fe]=De.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":a[F
e]=F(e);break;case"a":case"A":n._isPm=n._locale.isPM(e);break;case"h":case"hh":n._pf.bigHour=!0;case"H":case"HH":a[Ae]=F(e);break;case"m":case"mm":a[Ee]=F(e);break;case"s":case"ss":a[He]=F(e);break;case"S":case"SS":case"SSS":case"SSSS":a[Pe]=F(1e3*("0."+e));break;case"x":n._d=new Date(F(e));break;case"X":n._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":n._useUTC=!0,n._tzm=Z(e);break;case"dd":case"ddd":case"dddd":r=n._locale.weekdaysParse(e),null!=r?(n._w=n._w||{},n._w.d=r):n._pf.invalidWeekday=e;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":t=t.substr(0,1);case"gggg":case"GGGG":case"GGGGG":t=t.substr(0,2),e&&(n._w=n._w||{},n._w[t]=F(e));break;case"gg":case"GG":n._w=n._w||{},n._w[t]=De.parseTwoDigitYear(e)}}function R(t){var e,n,r,a,o,s,u;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(o=1,s=4,n=i(e.GG,t._a[Fe],de(De(),1,4).year),r=i(e.W,1),a=i(e.E,1)):(o=t._locale._week.dow,s=t._locale._week.doy,n=i(e.gg,t._a[Fe],de(De(),o,s).year),r=i(e.w,1),null!=e.d?(a=e.d,o>a&&
++r):a=null!=e.e?e.e+o:o),u=fe(n,r,a,s,o),t._a[Fe]=u.year,t._dayOfYear=u.dayOfYear}function $(t){var e,n,r,a,o=[];if(!t._d){for(r=Q(t),t._w&&null==t._a[Ie]&&null==t._a[Ce]&&R(t),t._dayOfYear&&(a=i(t._a[Fe],r[Fe]),t._dayOfYear>A(a)&&(t._pf._overflowDayOfYear=!0),n=se(a,0,t._dayOfYear),t._a[Ce]=n.getUTCMonth(),t._a[Ie]=n.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=o[e]=r[e];for(;7>e;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Ae]&&0===t._a[Ee]&&0===t._a[He]&&0===t._a[Pe]&&(t._nextDay=!0,t._a[Ae]=0),t._d=(t._useUTC?se:oe).apply(null,o),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()+t._tzm),t._nextDay&&(t._a[Ae]=24)}}function J(t){var e;t._d||(e=S(t._i),t._a=[e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],$(t))}function Q(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function X(t){if(t._f===De.ISO_8601)return ne(t),void 0;t._a=[],t._pf.empty=!0;var e,n,r,i
,o,s=""+t._i,u=s.length,c=0;for(r=V(t._f,t._locale).match(je)||[],e=0;e<r.length;e++)i=r[e],n=(s.match(B(i,t))||[])[0],n&&(o=s.substr(0,s.indexOf(n)),o.length>0&&t._pf.unusedInput.push(o),s=s.slice(s.indexOf(n)+n.length),c+=n.length),wn[i]?(n?t._pf.empty=!1:t._pf.unusedTokens.push(i),q(i,n,t)):t._strict&&!n&&t._pf.unusedTokens.push(i);t._pf.charsLeftOver=u-c,s.length>0&&t._pf.unusedInput.push(s),t._pf.bigHour===!0&&t._a[Ae]<=12&&(t._pf.bigHour=a),t._isPm&&t._a[Ae]<12&&(t._a[Ae]+=12),t._isPm===!1&&12===t._a[Ae]&&(t._a[Ae]=0),$(t),H(t)}function K(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,r,a){return e||n||r||a})}function te(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function ee(t){var e,n,r,a,i;if(0===t._f.length)return t._pf.invalidFormat=!0,t._d=new Date(0/0),void 0;for(a=0;a<t._f.length;a++)i=0,e=_({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._pf=s(),e._f=t._f[a],X(e),P(e)&&(i+=e._pf.charsLeftOver,i+=10*e._pf.unusedTokens.length,e._pf.scor
e=i,(null==r||r>i)&&(r=i,n=e));p(t,n||e)}function ne(t){var e,n,r=t._i,a=un.exec(r);if(a){for(t._pf.iso=!0,e=0,n=ln.length;n>e;e++)if(ln[e][1].exec(r)){t._f=ln[e][0]+(a[6]||" ");break}for(e=0,n=dn.length;n>e;e++)if(dn[e][1].exec(r)){t._f+=dn[e][0];break}r.match(Qe)&&(t._f+="Z"),X(t)}else t._isValid=!1}function re(t){ne(t),t._isValid===!1&&(delete t._isValid,De.createFromInputFallback(t))}function ae(t,e){var n,r=[];for(n=0;n<t.length;++n)r.push(e(t[n],n));return r}function ie(t){var e,n=t._i;n===a?t._d=new Date:Y(n)?t._d=new Date(+n):null!==(e=Ue.exec(n))?t._d=new Date(+e[1]):"string"==typeof n?re(t):k(n)?(t._a=ae(n.slice(0),function(t){return parseInt(t,10)}),$(t)):"object"==typeof n?J(t):"number"==typeof n?t._d=new Date(n):De.createFromInputFallback(t)}function oe(t,e,n,r,a,i,o){var s=new Date(t,e,n,r,a,i,o);return 1970>t&&s.setFullYear(t),s}function se(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function ue(t,e){if("string"==typeof t)if(
isNaN(t)){if(t=e.weekdaysParse(t),"number"!=typeof t)return null}else t=parseInt(t,10);return t}function ce(t,e,n,r,a){return a.relativeTime(e||1,!!n,t,r)}function le(t,e,n){var r=De.duration(t).abs(),a=Se(r.as("s")),i=Se(r.as("m")),o=Se(r.as("h")),s=Se(r.as("d")),u=Se(r.as("M")),c=Se(r.as("y")),l=a<_n.s&&["s",a]||1===i&&["m"]||i<_n.m&&["mm",i]||1===o&&["h"]||o<_n.h&&["hh",o]||1===s&&["d"]||s<_n.d&&["dd",s]||1===u&&["M"]||u<_n.M&&["MM",u]||1===c&&["y"]||["yy",c];return l[2]=e,l[3]=+t>0,l[4]=n,ce.apply({},l)}function de(t,e,n){var r,a=n-e,i=n-t.day();return i>a&&(i-=7),a-7>i&&(i+=7),r=De(t).add(i,"d"),{week:Math.ceil(r.dayOfYear()/7),year:r.year()}}function fe(t,e,n,r,a){var i,o,s=se(t,0,1).getUTCDay();return s=0===s?7:s,n=null!=n?n:a,i=a-s+(s>r?7:0)-(a>s?7:0),o=7*(e-1)+(n-a)+i+1,{year:o>0?t:t-1,dayOfYear:o>0?o:A(t-1)+o}}function he(t){var e,n=t._i,r=t._f;return t._locale=t._locale||De.localeData(t._l),null===n||r===a&&""===n?De.invalid({nullInput:!0}):("string"==typeof n&&(t._i=n=t.
_locale.preparse(n)),De.isMoment(n)?new m(n,!0):(r?k(r)?ee(t):X(t):ie(t),e=new m(t),e._nextDay&&(e.add(1,"d"),e._nextDay=a),e))}function me(t,e){var n,r;if(1===e.length&&k(e[0])&&(e=e[0]),!e.length)return De();for(n=e[0],r=1;r<e.length;++r)e[r][t](n)&&(n=e[r]);return n}function ye(t,e){var n;return"string"==typeof e&&(e=t.localeData().monthsParse(e),"number"!=typeof e)?t:(n=Math.min(t.date(),C(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t)}function pe(t,e){return t._d["get"+(t._isUTC?"UTC":"")+e]()}function _e(t,e,n){return"Month"===e?ye(t,n):t._d["set"+(t._isUTC?"UTC":"")+e](n)}function ve(t,e){return function(n){return null!=n?(_e(this,t,n),De.updateOffset(this,e),this):pe(this,t)}}function ge(t){return 400*t/146097}function we(t){return 146097*t/400}function be(t){De.duration.fn[t]=function(){return this._data[t]}}function Me(t){"undefined"==typeof ender&&(ke=xe.moment,xe.moment=t?c("Accessing Moment through the global scope is deprecated, and will be removed in an
upcoming release.",De):De)}for(var De,ke,Ye,Te="2.8.4",xe="undefined"!=typeof r?r:this,Se=Math.round,Oe=Object.prototype.hasOwnProperty,Fe=0,Ce=1,Ie=2,Ae=3,Ee=4,He=5,Pe=6,We={},Le=[],Ge="undefined"!=typeof n&&n&&n.exports,Ue=/^\/?Date\((\-?\d+)/i,Ne=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,ze=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,je=/(\[[^\[]*\])|(\\)?(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,Ve=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Be=/\d\d?/,Ze=/\d{1,3}/,qe=/\d{1,4}/,Re=/[+\-]?\d{1,6}/,$e=/\d+/,Je=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Qe=/Z|[\+\-]\d\d:?\d\d/gi,Xe=/T/i,Ke=/[\+\-]?\d+/,tn=/[\+\-]?\d+(\.\d{1,3})?/,en=/\d/,nn=/\d\d/,rn=/\d{3}/,an=/\d{4}/,on=/[+-]?\d{6}/,sn=/[+-]?\d+/,un=/^\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)?)?$/,cn="YYYY-MM-DDTHH:mm:ssZ",ln=[["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}/]],dn=[["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/]],fn=/([\+\-]|\d\d)/gi,hn=("Date|Hours|Minutes|Seconds|Milliseconds".split("|"),{Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6}),mn={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"},yn={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},pn={},_n={s:45,m:45,h:22,d:26,M:11},vn="DDD w W M D d".sp
lit(" "),gn="M D H h m s w W".split(" "),wn={M:function(){return this.month()+1},MMM:function(t){return this.localeData().monthsShort(this,t)},MMMM:function(t){return this.localeData().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.localeData().weekdaysMin(this,t)},ddd:function(t){return this.localeData().weekdaysShort(this,t)},dddd:function(t){return this.localeData().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return g(this.year()%100,2)},YYYY:function(){return g(this.year(),4)},YYYYY:function(){return g(this.year(),5)},YYYYYY:function(){var t=this.year(),e=t>=0?"+":"-";return e+g(Math.abs(t),6)},gg:function(){return g(this.weekYear()%100,2)},gggg:function(){return g(this.weekYear(),4)},ggggg:function(){return g(this.weekYear(),5)},GG:function(){return g(this.isoWeekYear()%100,2)},GGGG:function(){return g(this.isoWeekYear(),4
)},GGGGG:function(){return g(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 F(this.milliseconds()/100)},SS:function(){return g(F(this.milliseconds()/10),2)},SSS:function(){return g(this.milliseconds(),3)},SSSS:function(){return g(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+g(F(t/60),2)+":"+g(F(t)%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+g(F(t/60),2)+g(F(t)%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
()}},bn={},Mn=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];vn.length;)Ye=vn.pop(),wn[Ye+"o"]=f(wn[Ye],Ye);for(;gn.length;)Ye=gn.pop(),wn[Ye+Ye]=d(wn[Ye],2);wn.DDDD=d(wn.DDD,3),p(h.prototype,{set:function(t){var e,n;for(n in t)e=t[n],"function"==typeof e?this[n]=e:this["_"+n]=e;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(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t,e,n){var r,a,i;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),r=0;12>r;r++){if(a=De.utc([2e3,r]),n&&!this._longMonthsParse[r]&&(this._longMonthsParse[r]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[r]=new RegEx
p("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[r]||(i="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[r]=new RegExp(i.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[r].test(t))return r;if(n&&"MMM"===e&&this._shortMonthsParse[r].test(t))return r;if(!n&&this._monthsParse[r].test(t))return r}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,n,r;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(n=De([2e3,1]).day(e),r="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[e]=new RegExp(r.replace(".",""),"i"
)),this._weekdaysParse[e].test(t))return e},_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(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,n){return t>11?n?"pm":"PM":n?"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(t,e,n){var r=this._calendar[t];return"function"==typeof r?r.apply(e,[n]):r},_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(t,e,n,r){var a=this._relativeTime[n];return"function"==typeof a?a(t,e,n,r):a.replace(/%d/i,t)},pastFuture:function(t,e){var n=this._relativeTime[t>0?"future":"past"];return"function"==typeof n?n(e):n.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(t){return t},postformat:function(t){return t},week:function(t){return de(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),De=function(t,e,n,r){var i;return"boolean"==typeof n&&(r=n,n=a),i={},i._isAMomentObject=!0,i._i=t,i._f=e,i._l=n,i._strict=r,i._isUTC=!1,i._pf=s(),he(i)},De.suppressDeprecationWarnings=!1,De.createFromInputFallback=c("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(t){t._
d=new Date(t._i+(t._useUTC?" UTC":""))}),De.min=function(){var t=[].slice.call(arguments,0);return me("isBefore",t)},De.max=function(){var t=[].slice.call(arguments,0);return me("isAfter",t)},De.utc=function(t,e,n,r){var i;return"boolean"==typeof n&&(r=n,n=a),i={},i._isAMomentObject=!0,i._useUTC=!0,i._isUTC=!0,i._l=n,i._i=t,i._f=e,i._strict=r,i._pf=s(),he(i).utc()},De.unix=function(t){return De(1e3*t)},De.duration=function(t,e){var n,r,a,i,s=t,u=null;return De.isDuration(t)?s={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(s={},e?s[e]=t:s.milliseconds=t):(u=Ne.exec(t))?(n="-"===u[1]?-1:1,s={y:0,d:F(u[Ie])*n,h:F(u[Ae])*n,m:F(u[Ee])*n,s:F(u[He])*n,ms:F(u[Pe])*n}):(u=ze.exec(t))?(n="-"===u[1]?-1:1,a=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*n},s={y:a(u[2]),M:a(u[3]),d:a(u[4]),h:a(u[5]),m:a(u[6]),s:a(u[7]),w:a(u[8])}):"object"==typeof s&&("from"in s||"to"in s)&&(i=b(De(s.from),De(s.to)),s={},s.ms=i.milliseconds,s.M=i.months),r=new y(s),De.is
Duration(t)&&o(t,"_locale")&&(r._locale=t._locale),r},De.version=Te,De.defaultFormat=cn,De.ISO_8601=function(){},De.momentProperties=Le,De.updateOffset=function(){},De.relativeTimeThreshold=function(t,e){return _n[t]===a?!1:e===a?_n[t]:(_n[t]=e,!0)},De.lang=c("moment.lang is deprecated. Use moment.locale instead.",function(t,e){return De.locale(t,e)}),De.locale=function(t,e){var n;return t&&(n="undefined"!=typeof e?De.defineLocale(t,e):De.localeData(t),n&&(De.duration._locale=De._locale=n)),De._locale._abbr},De.defineLocale=function(t,e){return null!==e?(e.abbr=t,We[t]||(We[t]=new h),We[t].set(e),De.locale(t),We[t]):(delete We[t],null)},De.langData=c("moment.langData is deprecated. Use moment.localeData instead.",function(t){return De.localeData(t)}),De.localeData=function(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return De._locale;if(!k(t)){if(e=G(t))return e;t=[t]}return L(t)},De.isMoment=function(t){return t instanceof m||null!=t&&o(t,"_isAMomentObject")},
De.isDuration=function(t){return t instanceof y};for(Ye=Mn.length-1;Ye>=0;--Ye)O(Mn[Ye]);De.normalizeUnits=function(t){return x(t)},De.invalid=function(t){var e=De.utc(0/0);return null!=t?p(e._pf,t):e._pf.userInvalidated=!0,e},De.parseZone=function(){return De.apply(null,arguments).parseZone()},De.parseTwoDigitYear=function(t){return F(t)+(F(t)>68?1900:2e3)},p(De.fn=m.prototype,{clone:function(){return De(this)},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 t=De(this).utc();return 0<t.year()&&t.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():j(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):j(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.se
conds(),t.milliseconds()]},isValid:function(){return P(this)},isDSTShifted:function(){return this._a?this.isValid()&&T(this._a,(this._isUTC?De.utc(this._a):De(this._a)).toArray())>0:!1},parsingFlags:function(){return p({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(t){return this.zone(0,t)},local:function(t){return this._isUTC&&(this.zone(0,t),this._isUTC=!1,t&&this.add(this._dateTzOffset(),"m")),this},format:function(t){var e=j(this,t||De.defaultFormat);return this.localeData().postformat(e)},add:M(1,"add"),subtract:M(-1,"subtract"),diff:function(t,e,n){var r,a,i,o=U(t,this),s=6e4*(this.zone()-o.zone());return e=x(e),"year"===e||"month"===e?(r=432e5*(this.daysInMonth()+o.daysInMonth()),a=12*(this.year()-o.year())+(this.month()-o.month()),i=this-De(this).startOf("month")-(o-De(o).startOf("month")),i-=6e4*(this.zone()-De(this).startOf("month").zone()-(o.zone()-De(o).startOf("month").zone())),a+=i/r,"year"===e&&(a/=12)):(r=this-o,a="second"===e?r/1e3:"minute
"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-s)/864e5:"week"===e?(r-s)/6048e5:r),n?a:v(a)},from:function(t,e){return De.duration({to:this,from:t}).locale(this.locale()).humanize(!e)},fromNow:function(t){return this.from(De(),t)},calendar:function(t){var e=t||De(),n=U(e,this).startOf("day"),r=this.diff(n,"days",!0),a=-6>r?"sameElse":-1>r?"lastWeek":0>r?"lastDay":1>r?"sameDay":2>r?"nextDay":7>r?"nextWeek":"sameElse";return this.format(this.localeData().calendar(a,this,De(e)))},isLeapYear:function(){return E(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(t){var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ue(t,this.localeData()),this.add(t-e,"d")):e},month:ve("Month",!0),startOf:function(t){switch(t=x(t)){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"s
econd":this.milliseconds(0)}return"week"===t?this.weekday(0):"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(t){return t=x(t),t===a||"millisecond"===t?this:this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms")},isAfter:function(t,e){var n;return e=x("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=De.isMoment(t)?t:De(t),+this>+t):(n=De.isMoment(t)?+t:+De(t),n<+this.clone().startOf(e))},isBefore:function(t,e){var n;return e=x("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=De.isMoment(t)?t:De(t),+t>+this):(n=De.isMoment(t)?+t:+De(t),+this.clone().endOf(e)<n)},isSame:function(t,e){var n;return e=x(e||"millisecond"),"millisecond"===e?(t=De.isMoment(t)?t:De(t),+this===+t):(n=+De(t),+this.clone().startOf(e)<=n&&n<=+this.clone().endOf(e))},min:c("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(t){return t=De.apply(null,arguments),this>t?
this:t}),max:c("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(t){return t=De.apply(null,arguments),t>this?this:t}),zone:function(t,e){var n,r=this._offset||0;return null==t?this._isUTC?r:this._dateTzOffset():("string"==typeof t&&(t=Z(t)),Math.abs(t)<16&&(t=60*t),!this._isUTC&&e&&(n=this._dateTzOffset()),this._offset=t,this._isUTC=!0,null!=n&&this.subtract(n,"m"),r!==t&&(!e||this._changeInProgress?D(this,De.duration(r-t,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,De.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(t){return t=t?De(t).zone():0,(this.zone()-t)%60===0},daysInMonth:function(){return C(this.year(),this.month())},dayOfYear:functi
on(t){var e=Se((De(this).startOf("day")-De(this).startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},quarter:function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},weekYear:function(t){var e=de(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==t?e:this.add(t-e,"y")},isoWeekYear:function(t){var e=de(this,1,4).year;return null==t?e:this.add(t-e,"y")},week:function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},isoWeek:function(t){var e=de(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},weekday:function(t){var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return I(this.year(),1,4)},weeksInYear:function(){var t=this.localeData()._week;return I(this.year(),t.dow,t.doy)},get:function(t){return t=x(t),this[t]()},set:function(t,e){ret
urn t=x(t),"function"==typeof this[t]&&this[t](e),this},locale:function(t){var e;return t===a?this._locale._abbr:(e=De.localeData(t),null!=e&&(this._locale=e),this)
-},lang:c("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return t===a?this.localeData():this.locale(t)}),localeData:function(){return this._locale},_dateTzOffset:function(){return 15*Math.round(this._d.getTimezoneOffset()/15)}}),De.fn.millisecond=De.fn.milliseconds=ve("Milliseconds",!1),De.fn.second=De.fn.seconds=ve("Seconds",!1),De.fn.minute=De.fn.minutes=ve("Minutes",!1),De.fn.hour=De.fn.hours=ve("Hours",!0),De.fn.date=ve("Date",!0),De.fn.dates=c("dates accessor is deprecated. Use date instead.",ve("Date",!0)),De.fn.year=ve("FullYear",!0),De.fn.years=c("years accessor is deprecated. Use year instead.",ve("FullYear",!0)),De.fn.days=De.fn.day,De.fn.months=De.fn.month,De.fn.weeks=De.fn.week,De.fn.isoWeeks=De.fn.isoWeek,De.fn.quarters=De.fn.quarter,De.fn.toJSON=De.fn.toISOString,p(De.duration.fn=y.prototype,{_bubble:function(){var t,e,n,r=this._milliseconds,a=this._days,i=this
._months,o=this._data,s=0;o.milliseconds=r%1e3,t=v(r/1e3),o.seconds=t%60,e=v(t/60),o.minutes=e%60,n=v(e/60),o.hours=n%24,a+=v(n/24),s=v(ge(a)),a-=v(we(s)),i+=v(a/30),a%=30,s+=v(i/12),i%=12,o.days=a,o.months=i,o.years=s},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 v(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*F(this._months/12)},humanize:function(t){var e=le(this,!t,this.localeData());return t&&(e=this.localeData().pastFuture(+this,e)),this.localeData().postformat(e)},add:function(t,e){var n=De.duration(t,e);return
this._milliseconds+=n._milliseconds,this._days+=n._days,this._months+=n._months,this._bubble(),this},subtract:function(t,e){var n=De.duration(t,e);return this._milliseconds-=n._milliseconds,this._days-=n._days,this._months-=n._months,this._bubble(),this},get:function(t){return t=x(t),this[t.toLowerCase()+"s"]()},as:function(t){var e,n;if(t=x(t),"month"===t||"year"===t)return e=this._days+this._milliseconds/864e5,n=this._months+12*ge(e),"month"===t?n:n/12;switch(e=this._days+Math.round(we(this._months/12)),t){case"week":return e/7+this._milliseconds/6048e5;case"day":return e+this._milliseconds/864e5;case"hour":return 24*e+this._milliseconds/36e5;case"minute":return 24*e*60+this._milliseconds/6e4;case"second":return 24*e*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*e*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+t)}},lang:De.fn.lang,locale:De.fn.locale,toIsoString:c("toIsoString() is deprecated. Please use toISOString() instead (notice th
e capitals)",function(){return this.toISOString()}),toISOString:function(){var t=Math.abs(this.years()),e=Math.abs(this.months()),n=Math.abs(this.days()),r=Math.abs(this.hours()),a=Math.abs(this.minutes()),i=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(t?t+"Y":"")+(e?e+"M":"")+(n?n+"D":"")+(r||a||i?"T":"")+(r?r+"H":"")+(a?a+"M":"")+(i?i+"S":""):"P0D"},localeData:function(){return this._locale}}),De.duration.fn.toString=De.duration.fn.toISOString;for(Ye in hn)o(hn,Ye)&&be(Ye.toLowerCase());De.duration.fn.asMilliseconds=function(){return this.as("ms")},De.duration.fn.asSeconds=function(){return this.as("s")},De.duration.fn.asMinutes=function(){return this.as("m")},De.duration.fn.asHours=function(){return this.as("h")},De.duration.fn.asDays=function(){return this.as("d")},De.duration.fn.asWeeks=function(){return this.as("weeks")},De.duration.fn.asMonths=function(){return this.as("M")},De.duration.fn.asYears=function(){return
this.as("y")},De.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,n=1===F(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n}}),Ge?n.exports=De:"function"==typeof t&&t.amd?(t("moment",function(t,e,n){return n.config&&n.config()&&n.config().noGlobal===!0&&(xe.moment=ke),De}),Me(!0)):Me()}).call(this)}).call(this,"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],5:[function(t,e){for(var n=t("performance-now"),r="undefined"==typeof window?{}:window,a=["moz","webkit"],i="AnimationFrame",o=r["request"+i],s=r["cancel"+i]||r["cancelRequest"+i],u=!0,c=0;c<a.length&&!o;c++)o=r[a[c]+"Request"+i],s=r[a[c]+"Cancel"+i]||r[a[c]+"CancelRequest"+i];if(!o||!s){u=!1;var l=0,d=0,f=[],h=1e3/60;o=function(t){if(0===f.length){var e=n(),r=Math.max(0,h-(e-l));l=r+e,setTimeout(function(){var t=f.slice(0);f.length=0;for(var e=0;e<t.length;e++)if(!t[e].cancelled)try{t[e].callback(l)}catch(n){setTimeout(function(){throw n},0)}},Math.round(r))}r
eturn f.push({handle:++d,callback:t,cancelled:!1}),d},s=function(t){for(var e=0;e<f.length;e++)f[e].handle===t&&(f[e].cancelled=!0)}}e.exports=function(t){return u?o.call(r,function(){try{t.apply(this,arguments)}catch(e){setTimeout(function(){throw e},0)}}):o.call(r,t)},e.exports.cancel=function(){s.apply(r,arguments)}},{"performance-now":6}],6:[function(t,e){(function(t){(function(){var n,r,a;"undefined"!=typeof performance&&null!==performance&&performance.now?e.exports=function(){return performance.now()}:"undefined"!=typeof t&&null!==t&&t.hrtime?(e.exports=function(){return(n()-a)/1e6},r=t.hrtime,n=function(){var t;return t=r(),1e9*t[0]+t[1]},a=n()):Date.now?(e.exports=function(){return Date.now()-a},a=Date.now()):(e.exports=function(){return(new Date).getTime()-a},a=(new Date).getTime())}).call(this)}).call(this,t("FWaASH"))},{FWaASH:1}],7:[function(t,e){"use strict";function n(t,e){var n=u[t.id];return n&&n[e.id]}function r(t,e){var n=u[t.id];n||(n=u[t.id]={});var r=i(e);n[e.id
]=r,t.on("data",r),t.on("destroyed",a.bind(null,t,e))}function a(t,e){var n=u[t.id];if(n){var r=n[e.id];t.off("data",r),delete n[e.id]}}function i(t){return function(){t.refresh()}}function o(t,e){s(e.associated)||n(t,e)||r(t,e)}var s=t("./isInput"),u={};e.exports={add:o,remove:a}},{"./isInput":18}],8:[function(t,e){"use strict";function n(t){function e(){return Te}function n(n){return de=l(n||t,Te),me||(me=o({className:de.styles.container})),ye=de.weekdayFormat,pe=ye.length,ve=r,_e=r,ge=r,we=r,de.appendTo.appendChild(me),R(me),xe=!1,fe=de.initialValue?de.initialValue:d.moment(),he=fe.clone(),Te.container=me,Te.destroyed=!1,Te.destroy=p.bind(Te,!1),Te.emitValues=B,Te.getDate=ue,Te.getDateString=ce,Te.getMoment=le,Te.hide=C,Te.options=v,Te.options.reset=g,Te.refresh=Z,Te.restore=e,Te.setValue=q,Te.show=F,F(),_(),y(),Te}function y(){Te.emit("ready",c(de))}function p(t){me&&me.parentNode.removeChild(me),de&&_(!0);var r=Te.emitterSnapshot("destroyed");return Te.destroyed=!0,Te.destroy=e
,Te.emitValues=e,Te.getDate=m,Te.getDateString=m,Te.getMoment=m,Te.hide=e,Te.options=e,Te.options.reset=e,Te.refresh=e,Te.restore=n,Te.setValue=e,Te.show=e,Te.off(),t!==!0&&r(),Te}function _(t){var e=t?"remove":"add";de.autoHideOnBlur&&h[e](document.documentElement,"focus",E,!0),de.autoHideOnClick&&h[e](document,"click",H)}function v(t){return 0===arguments.length?c(de):(p(),n(t),Te)}function g(){return v({appendTo:de.appendTo})}function w(){xe||(xe=!0,b(),M(),Te.emit("render"))}function b(){function t(t){var e=o({className:de.styles.month,parent:be});0===t&&(Me=o({type:"button",className:de.styles.back,attributes:{type:"button"},parent:e})),t===de.monthsInCalendar-1&&(De=o({type:"button",className:de.styles.next,attributes:{type:"button"},parent:e}));var n,r=o({className:de.styles.monthLabel,parent:e}),a=o({type:"table",className:de.styles.dayTable,parent:e}),i=o({type:"thead",className:de.styles.dayHead,parent:a}),s=o({type:"tr",className:de.styles.dayRow,parent:i}),u=o({type:"tbo
dy",className:de.styles.dayBody,parent:a});for(n=0;pe>n;n++)o({type:"th",className:de.styles.dayHeadElem,parent:s,text:ye[D(n)]});u.setAttribute(Se,t),Oe.push({label:r,body:u})}if(de.date){var e;for(Oe=[],be=o({className:de.styles.date,parent:me}),e=0;e<de.monthsInCalendar;e++)t(e);h.add(Me,"click",P),h.add(De,"click",W),h.add(be,"click",re)}}function M(){if(de.time&&de.timeInterval){var t=o({className:de.styles.time,parent:me});ke=o({className:de.styles.selectedTime,parent:t,text:fe.format(de.timeFormat)}),h.add(ke,"click",Y),Ye=o({className:de.styles.timeList,parent:t}),h.add(Ye,"click",se);for(var e=d.moment("00:00:00","HH:mm:ss"),n=e.clone().add(1,"days");e.isBefore(n);)o({className:de.styles.timeOption,parent:Ye,text:e.format(de.timeFormat)}),e.add(de.timeInterval,"seconds")}}function D(t,e){var n=e?-1:1,r=t+de.weekStart*n;return(r>=pe||0>r)&&(r+=pe*-n),r}function k(){if(de.time&&xe){var t,e,n,r,a=Ye.children,i=a.length;for(r=0;i>r;r++)n=a[r],e=d.moment(s(n),de.timeFormat),t=oe
(fe.clone(),e),n.style.display=Q(t,!1,de.timeValidator)?"block":"none"}}function Y(t){var e="boolean"==typeof t?t:"none"===Ye.style.display;e?T():x()}function T(){Ye&&(Ye.style.display="block")}function x(){Ye&&(Ye.style.display="none")}function S(){me.style.display="inline-block",Te.emit("show")}function O(){me.style.display="none",Te.emit("hide")}function F(){return w(),Z(),Y(!de.date),S(),Te}function C(){return x(),i(O),Te}function I(){x();var t=f.contains(me,de.styles.positioned);return t&&i(O),Te}function A(t){var e=t.target;if(e===Te.associated)return!0;for(;e;){if(e===me)return!0;e=e.parentNode}}function E(t){A(t)||I()}function H(t){A(t)||I()}function P(){L("subtract")}function W(){L("add")}function L(t){var e,n="add"===t?-1:1,r=de.monthsInCalendar+n*ie(we);he[t](r,"months"),e=te(he.clone()),fe=e||fe,e&&(he=e.clone()),G()}function G(t){U(),V(),t!==!0&&B(),k()}function U(){function t(t,e){var n=he.clone().add(e,"months");s(t.label,n.format(de.monthFormat)),R(t.body)}if(de.date
&&xe){var e=he.year(),n=he.month(),r=he.date();if(r!==ge||n!==ve||e!==_e){var a=z();if(ge=he.date(),ve=he.month(),_e=he.year(),a)return N(),void 0;Oe.forEach(t),$()}}}function N(){function t(t){var e,n=[];for(e=0;e<t.length;e++)n.push(t[e]);return n}function e(e){return t(e.children)}function n(t){return!f.contains(t,de.styles.dayPrevMonth)&&!f.contains(t,de.styles.dayNextMonth)}var r=he.date()-1;ae(!1),Oe.forEach(function(a){var i;j(a.date,he)&&(i=t(a.body.children).map(e),i=Array.prototype.concat.apply([],i).filter(n),ae(i[r]))})}function z(){function t(t){return _e?j(t.date,he):!1}return Oe.some(t)}function j(t,e){return t&&e&&t.year()===e.year()&&t.month()===e.month()}function V(){de.time&&xe&&s(ke,fe.format(de.timeFormat))}function B(){return Te.emit("data",ce()),Te.emit("year",fe.year()),Te.emit("month",fe.month()),Te.emit("day",fe.day()),Te.emit("time",fe.format(de.timeFormat)),Te}function Z(){return _e=!1,ve=!1,ge=!1,G(!0),Te}function q(t){var e=u(t,de.inputFormat);if(null!=
=e)return fe=te(e)||fe,he=fe.clone(),G(!0),Te}function R(t,e){for(;t&&t.firstChild;)t.removeChild(t.firstChild);e===!0&&t.parentNode.removeChild(t)}function $(){var t;for(t=0;t<de.monthsInCalendar;t++)J(t)}function J(t){function e(t){var e,r,a;for(e=0;e<t.length;e++)f.children.length===pe&&(f=o({type:"tr",className:de.styles.dayRow,parent:i.body})),r=t.base.clone().add(e,"days"),a=o({type:"td",parent:f,text:r.format(de.dayFormat),className:n(r,t.cell.join(" ").split(" ")).join(" ")}),t.selectable&&r.date()===c&&ae(a)}function n(t,e){return Q(t,!0,de.dateValidator)||e.push(y),e}function r(t,e){return t&&e.push(de.styles.dayConcealed),e}var a,i=Oe[t],s=he.clone().add(t,"months"),u=s.daysInMonth(),c=s.month()!==fe.month()?-1:fe.date(),l=s.clone().date(1),d=D(l.day(),!0),f=o({type:"tr",className:de.styles.dayRow,parent:i.body}),h=r(0!==t,[de.styles.dayBodyElem,de.styles.dayPrevMonth]),m=r(t!==de.monthsInCalendar-1,[de.styles.dayBodyElem,de.styles.dayNextMonth]),y=de.styles.dayDisabled;e
({base:l.clone().subtract(d,"days"),length:d,cell:h}),e({base:l.clone(),length:u,cell:[de.styles.dayBodyElem],selectable:!0}),a=l.clone().add(u,"days"),e({base:a,length:pe-f.children.length,cell:m}),Me.disabled=!X(l,!0),De.disabled=!K(a,!0),i.date=s.clone()}function Q(t,e,n){if(!X(t,e))return!1;if(!K(t,e))return!1;var r=(n||Function.prototype).call(Te,t.toDate());return r!==!1}function X(t,e){var n=de.min?e?de.min.clone().startOf("day"):de.min:!1;return!n||!t.isBefore(n)}function K(t,e){var n=de.max?e?de.max.clone().endOf("day"):de.max:!1;return!n||!t.isAfter(n)}function te(t){if(de.min&&t.isBefore(de.min))return te(de.min.clone());if(de.max&&t.isAfter(de.max))return te(de.max.clone());var e=t.clone().subtract(1,"days");return ne(e,t,"add")?ee(e):(e=t.clone(),ne(e,t,"subtract")?ee(e):void 0)}function ee(t){var e,n=t.clone().subtract(de.timeInterval,"seconds"),r=Math.ceil(Fe/de.timeInterval);for(e=0;r>e;e++)if(n.add(de.timeInterval,"seconds"),n.date()>t.date()&&n.subtract(1,"days"),d
e.timeValidator.call(Te,n.toDate())!==!1)return n}function ne(t,e,n){for(var r=!1;r===!1&&(t[n](1,"days"),t.month()===e.month());)r=de.dateValidator.call(Te,t.toDate());return r!==!1}function re(t){var e=t.target;if(!f.contains(e,de.styles.dayDisabled)&&f.contains(e,de.styles.dayBodyElem)){var n=parseInt(s(e),10),r=f.contains(e,de.styles.dayPrevMonth),a=f.contains(e,de.styles.dayNextMonth),i=ie(e)-ie(we);fe.add(i,"months"),(r||a)&&fe.add(r?-1:1,"months"),ae(e),fe.date(n),oe(fe,te(fe)||fe),he=fe.clone(),de.autoClose===!0&&I(),G()}}function ae(t){we&&f.remove(we,de.styles.selectedDay),t&&f.add(t,de.styles.selectedDay),we=t}function ie(t){for(var e;t&&t.getAttribute;){if(e=t.getAttribute(Se),"string"==typeof e)return parseInt(e,10);t=t.parentNode}return 0}function oe(t,e){return t.hour(e.hour()).minute(e.minute()).second(e.second()),t}function se(t){var e=t.target;if(f.contains(e,de.styles.timeOption)){var n=d.moment(s(e),de.timeFormat);oe(fe,n),he=fe.clone(),B(),V(),!de.date&&de.autoC
lose===!0||"time"===de.autoClose?I():x()}}function ue(){return fe.toDate()}function ce(t){return fe.format(t||de.inputFormat)}function le(){return fe.clone()}var de,fe,he,me,ye,pe,_e,ve,ge,we,be,Me,De,ke,Ye,Te=a({}),xe=!1,Se="data-rome-offset",Oe=[],Fe=86400;return n(),i(y),Te}var r,a=t("contra.emitter"),i=t("raf"),o=t("./dom"),s=t("./text"),u=t("./parse"),c=t("./clone"),l=t("./defaults"),d=t("./momentum"),f=t("./classes"),h=t("./events"),m=t("./noop");e.exports=n},{"./classes":9,"./clone":10,"./defaults":12,"./dom":13,"./events":14,"./momentum":19,"./noop":20,"./parse":21,"./text":33,"contra.emitter":2,raf:5}],9:[function(t,e){"use strict";function n(t){return t.className.replace(s,"").split(u)}function r(t,e){t.className=e.join(" ")}function a(t,e){var n=i(t,e);n.push(e),r(t,n)}function i(t,e){var a=n(t),i=a.indexOf(e);return-1!==i&&(a.splice(i,1),r(t,a)),a}function o(t,e){return-1!==n(t).indexOf(e)}var s=/^\s+|\s+$/g,u=/\s+/;e.exports={add:a,remove:i,contains:o}},{}],10:[function
(t,e){"use strict";function n(t){var e,a={};for(var i in t)e=t[i],a[i]=e?r.isMoment(e)?e.clone():e._isStylesConfiguration?n(e):e:e;return a}var r=t("./momentum");e.exports=n},{"./momentum":19}],11:[function(t,e){"use strict";function n(t,e){var n,s=r.find(t);return s?s:(n=o(t)?a(t,e):i(t,e),n.associated=t,r.assign(t,n),n)}var r=t("./index"),a=t("./input"),i=t("./inline"),o=t("./isInput");e.exports=n},{"./index":15,"./inline":16,"./input":17,"./isInput":18}],12:[function(t,e){"use strict";function n(t,e){var n,o,s=t||{};if(s.autoHideOnClick===o&&(s.autoHideOnClick=!0),s.autoHideOnBlur===o&&(s.autoHideOnBlur=!0),s.autoClose===o&&(s.autoClose=!0),s.appendTo===o&&(s.appendTo=document.body),"parent"===s.appendTo){if(!a(e.associated))throw new Error("Inline calendars must be appended to a parent node explicitly.");s.appendTo=e.associated.parentNode}if(s.invalidate===o&&(s.invalidate=!0),s.required===o&&(s.required=!1),s.date===o&&(s.date=!0),s.time===o&&(s.time=!0),s.date===!1&&s.time===!
1)throw new Error("At least one of `date` or `time` must be `true`.");if(s.inputFormat===o&&(s.inputFormat=s.date&&s.time?"YYYY-MM-DD HH:mm":s.date?"YYYY-MM-DD":"HH:mm"),s.initialValue=s.initialValue===o?null:r(s.initialValue,s.inputFormat),s.min=s.min===o?null:r(s.min,s.inputFormat),s.max=s.max===o?null:r(s.max,s.inputFormat),s.timeInterval===o&&(s.timeInterval=1800),s.min&&s.max)if(s.max.isBefore(s.min)&&(n=s.max,s.max=s.min,s.min=n),s.date===!0){if(s.max.clone().subtract(1,"days").isBefore(s.min))throw new Error("`max` must be at least one day after `min`")}else if(1e3*s.timeInterval-s.min%(1e3*s.timeInterval)>s.max-s.min)throw new Error("`min` to `max` range must allow for at least one time option that matches `timeInterval`");if(s.dateValidator===o&&(s.dateValidator=Function.prototype),s.timeValidator===o&&(s.timeValidator=Function.prototype),s.timeFormat===o&&(s.timeFormat="HH:mm"),s.weekStart===o&&(s.weekStart=i.moment().weekday(0).day()),s.weekdayFormat===o&&(s.weekdayFormat
="min"),"long"===s.weekdayFormat)s.weekdayFormat=i.moment.weekdays();else if("short"===s.weekdayFormat)s.weekdayFormat=i.moment.weekdaysShort();else if("min"===s.weekdayFormat)s.weekdayFormat=i.moment.weekdaysMin();else if(!Array.isArray(s.weekdayFormat)||s.weekdayFormat.length<7)throw new Error("`weekdays` must be `min`, `short`, or `long`");s.monthsInCalendar===o&&(s.monthsInCalendar=1),s.monthFormat===o&&(s.monthFormat="MMMM YYYY"),s.dayFormat===o&&(s.dayFormat="DD"),s.styles===o&&(s.styles={}),s.styles._isStylesConfiguration=!0;var u=s.styles;return u.back===o&&(u.back="rd-back"),u.container===o&&(u.container="rd-container"),u.positioned===o&&(u.positioned="rd-container-attachment"),u.date===o&&(u.date="rd-date"),u.dayBody===o&&(u.dayBody="rd-days-body"),u.dayBodyElem===o&&(u.dayBodyElem="rd-day-body"),u.dayPrevMonth===o&&(u.dayPrevMonth="rd-day-prev-month"),u.dayNextMonth===o&&(u.dayNextMonth="rd-day-next-month"),u.dayDisabled===o&&(u.dayDisabled="rd-day-disabled"),u.dayConceal
ed===o&&(u.dayConcealed="rd-day-concealed"),u.dayHead===o&&(u.dayHead="rd-days-head"),u.dayHeadElem===o&&(u.dayHeadElem="rd-day-head"),u.dayRow===o&&(u.dayRow="rd-days-row"),u.dayTable===o&&(u.dayTable="rd-days"),u.month===o&&(u.month="rd-month"),u.monthLabel===o&&(u.monthLabel="rd-month-label"),u.next===o&&(u.next="rd-next"),u.selectedDay===o&&(u.selectedDay="rd-day-selected"),u.selectedTime===o&&(u.selectedTime="rd-time-selected"),u.time===o&&(u.time="rd-time"),u.timeList===o&&(u.timeList="rd-time-list"),u.timeOption===o&&(u.timeOption="rd-time-option"),s}var r=t("./parse"),a=t("./isInput"),i=t("./momentum");e.exports=n},{"./isInput":18,"./momentum":19,"./parse":21}],13:[function(t,e){"use strict";function n(t){var e=t||{};e.type||(e.type="div");var n=document.createElement(e.type);return e.className&&(n.className=e.className),e.text&&(n.innerText=n.textContent=e.text),e.attributes&&Object.keys(e.attributes).forEach(function(t){n.setAttribute(t,e.attributes[t])}),e.parent&&e.paren
t.appendChild(n),n}e.exports=n},{}],14:[function(t,e){"use strict";function n(t,e,n,r){return t.addEventListener(e,n,r)}function r(t,e,n,r){return t.attachEvent("on"+e,function(e){var r=e||window.event;r.target=r.target||r.srcElement,r.preventDefault=r.preventDefault||function(){r.returnValue=!1},r.stopPropagation=r.stopPropagation||function(){r.cancelBubble=!0},n.call(t,r)},r)}function a(t,e,n){return t.removeEventListener(e,n)}function i(t,e,n){return t.detachEvent("on"+e,n)}var o=n,s=a;window.addEventListener||(o=r),window.removeEventListener||(s=i),e.exports={add:o,remove:s}},{}],15:[function(t,e){"use strict";function n(t){if("number"!=typeof t&&t&&t.getAttribute)return n(t.getAttribute(i));var e=o[t];return e!==a?e:null}function r(t,e){t.setAttribute(i,e.id=o.push(e)-1)}var a,i="data-rome-id",o=[];e.exports={find:n,assign:r}},{}],16:[function(t,e){"use strict";function n(t,e){var n=e||{};return n.appendTo=t,r(n)}var r=(t("raf"),t("./calendar"));e.exports=n},{"./calendar":8,raf
:5}],17:[function(t,e){"use strict";function n(t,e){function n(n){b=i(n||e,k),u.add(k.container,b.styles.positioned),c.add(k.container,"mousedown",h),c.add(k.container,"click",f),k.getDate=w(k.getDate),k.getDateString=w(k.getDateString),k.getMoment=w(k.getMoment),b.initialValue&&(t.value=b.initialValue.format(b.inputFormat)),k.on("data",v),k.on("show",T),d(),Y(),k.hide()}function l(){d(!0)}function d(e){var r=e?"remove":"add";c[r](t,"click",y),c[r](t,"touchend",y),c[r](t,"focusin",y),c[r](t,"change",Y),c[r](t,"keypress",Y),c[r](t,"keydown",Y),c[r](t,"input",Y),b.invalidate&&c[r](t,"blur",m),c[r](window,"resize",T),e?(k.once("ready",n),k.off("destroyed",l)):(k.off("ready",n),k.once("destroyed",l))}function f(){D=!0,t.focus(),D=!1}function h(){function t(){M=!1}M=!0,a(t)}function m(){M||g()||k.emitValues()}function y(){D||k.show()}function p(){var e=t.getBoundingClientRect(),n=document.body.scrollTop||document.documentElement.scrollTop;k.container.style.top=e.top+n+t.offsetHeight+"px"
,k.container.style.left=e.left+"px"}function _(){var e=t.value.trim();if(!g()){var n=s.moment(e,b.inputFormat,b.strictParse);k.setValue(n)}}function v(e){t.value=e}function g(){return b.required===!1&&""===t.value.trim()}function w(t){return function(){return g()?null:t.apply(this,arguments)}}var b,M,D,k=o(e),Y=r(_,30),T=r(p,30);return n(e),k}var r=t("./throttle"),a=t("raf"),i=(t("./clone"),t("./defaults")),o=t("./calendar"),s=t("./momentum"),u=t("./classes"),c=t("./events");e.exports=n},{"./calendar":8,"./classes":9,"./clone":10,"./defaults":12,"./events":14,"./momentum":19,"./throttle":34,raf:5}],18:[function(t,e){"use strict";function n(t){return t&&t.nodeName&&"input"===t.nodeName.toLowerCase()}e.exports=n},{}],19:[function(t,e){"use strict";function n(t){return t&&Object.prototype.hasOwnProperty.call(t,"_isAMomentObject")}var r={moment:null,isMoment:n};e.exports=r},{}],20:[function(t,e){"use strict";function n(){}e.exports=n},{}],21:[function(t,e){"use strict";function n(t,e){r
eturn"string"==typeof t?a.moment(t,e):"[object Date]"===Object.prototype.toString.call(t)?a.moment(t):a.isMoment(t)?t.clone():void 0}function r(t,e){var r=n(t,"string"==typeof e?e:null);return r&&r.isValid()?r:null}var a=t("./momentum");e.exports=r},{"./momentum":19}],22:[function(){"use strict";Array.prototype.filter||(Array.prototype.filter=function(t,e){var n=[];return this.forEach(function(r,a,i){t.call(e,r,a,i)&&n.push(r)},e),n})},{}],23:[function(){"use strict";Array.prototype.forEach||(Array.prototype.forEach=function(t,e){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var n=this,r=n.length,a=0;r>a;a++)a in n&&t.call(e,n[a],a,n)})},{}],24:[function(){"use strict";Array.prototype.indexOf||(Array.prototype.indexOf=function(t,e){if(void 0===this||null===this)throw new TypeError;var n=this.length;for(e=+e||0,1/0===Math.abs(e)?e=0:0>e&&(e+=n,0>e&&(e=0));n>e;e++)if(this[e]===t)return e;return-1})},{}],25:[function(){"use strict";Array.isArray||(Array.is
Array=function(t){return""+t!==t&&"[object Array]"===Object.prototype.toString.call(t)})},{}],26:[function(){"use strict";Array.prototype.map||(Array.prototype.map=function(t,e){var n,r,a;if(null==this)throw new TypeError("this is null or not defined");var i=Object(this),o=i.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),r=new Array(o),a=0;o>a;)a in i&&(r[a]=t.call(n,i[a],a,i)),a++;return r})},{}],27:[function(){"use strict";Array.prototype.some||(Array.prototype.some=function(t,e){var n,r;if(null==this)throw new TypeError("this is null or not defined");var a=Object(this),i=a.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),r=0;i>r;){if(r in a){var o=t.call(n,a[r],r,a);if(o)return!0}r++}return!1})},{}],28:[function(){"use strict";Function.prototype.bind||(Function.prototype.bind=function(t){if("function"!=typeof this)throw new TypeError("Function.prototype.bind -
what is trying to be bound is not callable");var e=Array.prototype.slice.call(arguments,1),n=this,r=function(){},a=function(){var a=this instanceof r&&t?this:t,i=e.concat(Array.prototype.slice.call(arguments));return n.apply(a,i)};return r.prototype=this.prototype,a.prototype=new r,a})},{}],29:[function(){"use strict";var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=n.length;Object.keys||(Object.keys=function(a){if("object"!=typeof a&&("function"!=typeof a||null===a))throw new TypeError("Object.keys called on non-object");var i,o,s=[];for(i in a)t.call(a,i)&&s.push(i);if(e)for(o=0;r>o;o++)t.call(a,n[o])&&s.push(n[o]);return s})},{}],30:[function(){"use strict";String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")})},{}],31:[function(t,e){"use strict";t("./polyfills/function.bind"),t("./poly
fills/array.foreach"),t("./polyfills/array.map"),t("./polyfills/array.filter"),t("./polyfills/array.isarray"),t("./polyfills/array.indexof"),t("./polyfills/array.some"),t("./polyfills/string.trim"),t("./polyfills/object.keys");var n=t("./core"),r=t("./index"),a=t("./use");n.use=a.bind(n),n.find=r.find,n.val=t("./validators"),e.exports=n},{"./core":11,"./index":15,"./polyfills/array.filter":22,"./polyfills/array.foreach":23,"./polyfills/array.indexof":24,"./polyfills/array.isarray":25,"./polyfills/array.map":26,"./polyfills/array.some":27,"./polyfills/function.bind":28,"./polyfills/object.keys":29,"./polyfills/string.trim":30,"./use":35,"./validators":36}],32:[function(t,e){"use strict";var n=t("moment"),r=t("./rome");r.use(n),e.exports=r},{"./rome":31,moment:4}],33:[function(t,e){"use strict";function n(t,e){return 2===arguments.length&&(t.innerText=t.textContent=e),t.innerText||t.textContent}e.exports=n},{}],34:[function(t,e){"use strict";e.exports=function(t,e){var n,r=-1/0;return
function(){function a(){clearTimeout(n),n=null;var i=r+e,o=Date.now();o>i?(r=o,t.apply(this,arguments)):n=setTimeout(a,i-o)}n||a()}}},{}],35:[function(t,e){"use strict";function n(t){this.moment=r.moment=t}var r=t("./momentum");e.exports=n},{"./momentum":19}],36:[function(t,e){"use strict";function n(t){return function(e){var n=i(e);return function(r){var s=a.find(e),u=i(r),c=n||s&&s.getMoment();return c?(s&&o.add(this,s),t(u,c)):!0}}}function r(t,e){return function(n,r){function s(t){var e,n,r=a.find(t);return r?e=n=r.getMoment():Array.isArray(t)?(e=t[0],n=t[1]):e=n=t,r&&o.add(r,this),{start:i(e).startOf("day").toDate(),end:i(n).endOf("day").toDate()}}var u,c=arguments.length;return Array.isArray(n)?u=n:1===c?u=[n]:2===c&&(u=[[n,r]]),function(n){return u.map(s.bind(this))[t](e.bind(this,n))}}}var a=t("./index"),i=t("./parse"),o=t("./association"),s=n(function(t,e){return t>=e}),u=n(function(t,e){return t>e}),c=n(function(t,e){return e>=t}),l=n(function(t,e){return e>t}),d=r("every
",function(t,e){return e.start>t||e.end<t}),f=r("some",function(t,e){return e.start<=t&&e.end>=t});e.exports={afterEq:s,after:u,beforeEq:c,before:l,except:d,only:f}},{"./association":7,"./index":15,"./parse":21}]},{},[32])(32)});
\ No newline at end of file
[10/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/backgrid-paginator-0.3.5.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/backgrid-paginator-0.3.5.js b/htrace-htraced/src/web/lib/js/backgrid-paginator-0.3.5.js
deleted file mode 100644
index 64dd434..0000000
--- a/htrace-htraced/src/web/lib/js/backgrid-paginator-0.3.5.js
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- backgrid-paginator
- http://github.com/wyuenho/backgrid
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
- Licensed under the MIT @license.
-*/
-(function (root, factory) {
-
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(require("underscore"),
- require("backbone"),
- require("backgrid"),
- require("backbone.paginator"));
- }
- // AMD. Register as an anonymous module.
- else if (typeof define === 'function' && define.amd) {
- define(['underscore', 'backbone', 'backgrid', 'backbone.paginator'], factory);
- }
- // Browser
- else {
- factory(root._, root.Backbone, root.Backgrid);
- }
-
-}(this, function (_, Backbone, Backgrid) {
-
- "use strict";
-
- /**
- PageHandle is a class that renders the actual page handles and reacts to
- click events for pagination.
-
- This class acts in two modes - control or discrete page handle modes. If
- one of the `is*` flags is `true`, an instance of this class is under
- control page handle mode. Setting a `pageIndex` to an instance of this
- class under control mode has no effect and the correct page index will
- always be inferred from the `is*` flag. Only one of the `is*` flags should
- be set to `true` at a time. For example, an instance of this class cannot
- simultaneously be a rewind control and a fast forward control. A `label`
- and a `title` function or a string are required to be passed to the
- constuctor under this mode. If a `title` function is provided, it __MUST__
- accept a hash parameter `data`, which contains a key `label`. Its result
- will be used to render the generated anchor's title attribute.
-
- If all of the `is*` flags is set to `false`, which is the default, an
- instance of this class will be in discrete page handle mode. An instance
- under this mode requires the `pageIndex` to be passed from the constructor
- as an option and it __MUST__ be a 0-based index of the list of page numbers
- to render. The constuctor will normalize the base to the same base the
- underlying PageableCollection collection instance uses. A `label` is not
- required under this mode, which will default to the equivalent 1-based page
- index calculated from `pageIndex` and the underlying PageableCollection
- instance. A provided `label` will still be honored however. The `title`
- parameter is also not required under this mode, in which case the default
- `title` function will be used. You are encouraged to provide your own
- `title` function however if you wish to localize the title strings.
-
- If this page handle represents the current page, an `active` class will be
- placed on the root list element.
-
- If this page handle is at the border of the list of pages, a `disabled`
- class will be placed on the root list element.
-
- Only page handles that are neither `active` nor `disabled` will respond to
- click events and triggers pagination.
-
- @class Backgrid.Extension.PageHandle
- */
- var PageHandle = Backgrid.Extension.PageHandle = Backbone.View.extend({
-
- /** @property */
- tagName: "li",
-
- /** @property */
- events: {
- "click a": "changePage"
- },
-
- /**
- @property {string|function(Object.<string, string>): string} title
- The title to use for the `title` attribute of the generated page handle
- anchor elements. It can be a string or a function that takes a `data`
- parameter, which contains a mandatory `label` key which provides the
- label value to be displayed.
- */
- title: function (data) {
- return 'Page ' + data.label;
- },
-
- /**
- @property {boolean} isRewind Whether this handle represents a rewind
- control
- */
- isRewind: false,
-
- /**
- @property {boolean} isBack Whether this handle represents a back
- control
- */
- isBack: false,
-
- /**
- @property {boolean} isForward Whether this handle represents a forward
- control
- */
- isForward: false,
-
- /**
- @property {boolean} isFastForward Whether this handle represents a fast
- forward control
- */
- isFastForward: false,
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Collection} options.collection
- @param {number} pageIndex 0-based index of the page number this handle
- handles. This parameter will be normalized to the base the underlying
- PageableCollection uses.
- @param {string} [options.label] If provided it is used to render the
- anchor text, otherwise the normalized pageIndex will be used
- instead. Required if any of the `is*` flags is set to `true`.
- @param {string} [options.title]
- @param {boolean} [options.isRewind=false]
- @param {boolean} [options.isBack=false]
- @param {boolean} [options.isForward=false]
- @param {boolean} [options.isFastForward=false]
- */
- initialize: function (options) {
- var collection = this.collection;
- var state = collection.state;
- var currentPage = state.currentPage;
- var firstPage = state.firstPage;
- var lastPage = state.lastPage;
-
- _.extend(this, _.pick(options,
- ["isRewind", "isBack", "isForward", "isFastForward"]));
-
- var pageIndex;
- if (this.isRewind) pageIndex = firstPage;
- else if (this.isBack) pageIndex = Math.max(firstPage, currentPage - 1);
- else if (this.isForward) pageIndex = Math.min(lastPage, currentPage + 1);
- else if (this.isFastForward) pageIndex = lastPage;
- else {
- pageIndex = +options.pageIndex;
- pageIndex = (firstPage ? pageIndex + 1 : pageIndex);
- }
- this.pageIndex = pageIndex;
-
- this.label = (options.label || (firstPage ? pageIndex : pageIndex + 1)) + '';
- var title = options.title || this.title;
- this.title = _.isFunction(title) ? title({label: this.label}) : title;
- },
-
- /**
- Renders a clickable anchor element under a list item.
- */
- render: function () {
- this.$el.empty();
- var anchor = document.createElement("a");
- anchor.href = '#';
- if (this.title) anchor.title = this.title;
- anchor.innerHTML = this.label;
- this.el.appendChild(anchor);
-
- var collection = this.collection;
- var state = collection.state;
- var currentPage = state.currentPage;
- var pageIndex = this.pageIndex;
-
- if (this.isRewind && currentPage == state.firstPage ||
- this.isBack && !collection.hasPreviousPage() ||
- this.isForward && !collection.hasNextPage() ||
- this.isFastForward && (currentPage == state.lastPage || state.totalPages < 1)) {
- this.$el.addClass("disabled");
- }
- else if (!(this.isRewind ||
- this.isBack ||
- this.isForward ||
- this.isFastForward) &&
- state.currentPage == pageIndex) {
- this.$el.addClass("active");
- }
-
- this.delegateEvents();
- return this;
- },
-
- /**
- jQuery click event handler. Goes to the page this PageHandle instance
- represents. No-op if this page handle is currently active or disabled.
- */
- changePage: function (e) {
- e.preventDefault();
- var $el = this.$el, col = this.collection;
- if (!$el.hasClass("active") && !$el.hasClass("disabled")) {
- if (this.isRewind) col.getFirstPage();
- else if (this.isBack) col.getPreviousPage();
- else if (this.isForward) col.getNextPage();
- else if (this.isFastForward) col.getLastPage();
- else col.getPage(this.pageIndex, {reset: true});
- }
- return this;
- }
-
- });
-
- /**
- Paginator is a Backgrid extension that renders a series of configurable
- pagination handles. This extension is best used for splitting a large data
- set across multiple pages. If the number of pages is larger then a
- threshold, which is set to 10 by default, the page handles are rendered
- within a sliding window, plus the rewind, back, forward and fast forward
- control handles. The individual control handles can be turned off.
-
- @class Backgrid.Extension.Paginator
- */
- var Paginator = Backgrid.Extension.Paginator = Backbone.View.extend({
-
- /** @property */
- className: "backgrid-paginator",
-
- /** @property */
- windowSize: 10,
-
- /**
- @property {number} slideScale the number used by #slideHowMuch to scale
- `windowSize` to yield the number of pages to slide. For example, the
- default windowSize(10) * slideScale(0.5) yields 5, which means the window
- will slide forward 5 pages as soon as you've reached page 6. The smaller
- the scale factor the less pages to slide, and vice versa.
-
- Also See:
-
- - #slideMaybe
- - #slideHowMuch
- */
- slideScale: 0.5,
-
- /**
- @property {Object.<string, Object.<string, string>>} controls You can
- disable specific control handles by setting the keys in question to
- null. The defaults will be merged with your controls object, with your
- changes taking precedent.
- */
- controls: {
- rewind: {
- label: "《",
- title: "First"
- },
- back: {
- label: "〈",
- title: "Previous"
- },
- forward: {
- label: "〉",
- title: "Next"
- },
- fastForward: {
- label: "》",
- title: "Last"
- }
- },
-
- /** @property */
- renderIndexedPageHandles: true,
-
- /**
- @property {Backgrid.Extension.PageHandle} pageHandle. The PageHandle
- class to use for rendering individual handles
- */
- pageHandle: PageHandle,
-
- /** @property */
- goBackFirstOnSort: true,
-
- /**
- Initializer.
-
- @param {Object} options
- @param {Backbone.Collection} options.collection
- @param {boolean} [options.controls]
- @param {boolean} [options.pageHandle=Backgrid.Extension.PageHandle]
- @param {boolean} [options.goBackFirstOnSort=true]
- */
- initialize: function (options) {
- var self = this;
- self.controls = _.defaults(options.controls || {}, self.controls,
- Paginator.prototype.controls);
-
- _.extend(self, _.pick(options || {}, "windowSize", "pageHandle",
- "slideScale", "goBackFirstOnSort",
- "renderIndexedPageHandles"));
-
- var col = self.collection;
- self.listenTo(col, "add", self.render);
- self.listenTo(col, "remove", self.render);
- self.listenTo(col, "reset", self.render);
- self.listenTo(col, "backgrid:sorted", function () {
- if (self.goBackFirstOnSort) col.getFirstPage({reset: true});
- });
- },
-
- /**
- Decides whether the window should slide. This method should return 1 if
- sliding should occur and 0 otherwise. The default is sliding should occur
- if half of the pages in a window has been reached.
-
- __Note__: All the parameters have been normalized to be 0-based.
-
- @param {number} firstPage
- @param {number} lastPage
- @param {number} currentPage
- @param {number} windowSize
- @param {number} slideScale
-
- @return {0|1}
- */
- slideMaybe: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
- return Math.round(currentPage % windowSize / windowSize);
- },
-
- /**
- Decides how many pages to slide when sliding should occur. The default
- simply scales the `windowSize` to arrive at a fraction of the `windowSize`
- to increment.
-
- __Note__: All the parameters have been normalized to be 0-based.
-
- @param {number} firstPage
- @param {number} lastPage
- @param {number} currentPage
- @param {number} windowSize
- @param {number} slideScale
-
- @return {number}
- */
- slideThisMuch: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
- return ~~(windowSize * slideScale);
- },
-
- _calculateWindow: function () {
- var collection = this.collection;
- var state = collection.state;
-
- // convert all indices to 0-based here
- var firstPage = state.firstPage;
- var lastPage = +state.lastPage;
- lastPage = Math.max(0, firstPage ? lastPage - 1 : lastPage);
- var currentPage = Math.max(state.currentPage, state.firstPage);
- currentPage = firstPage ? currentPage - 1 : currentPage;
- var windowSize = this.windowSize;
- var slideScale = this.slideScale;
- var windowStart = Math.floor(currentPage / windowSize) * windowSize;
- if (currentPage <= lastPage - this.slideThisMuch()) {
- windowStart += (this.slideMaybe(firstPage, lastPage, currentPage, windowSize, slideScale) *
- this.slideThisMuch(firstPage, lastPage, currentPage, windowSize, slideScale));
- }
- var windowEnd = Math.min(lastPage + 1, windowStart + windowSize);
- return [windowStart, windowEnd];
- },
-
- /**
- Creates a list of page handle objects for rendering.
-
- @return {Array.<Object>} an array of page handle objects hashes
- */
- makeHandles: function () {
-
- var handles = [];
- var collection = this.collection;
-
- var window = this._calculateWindow();
- var winStart = window[0], winEnd = window[1];
-
- if (this.renderIndexedPageHandles) {
- for (var i = winStart; i < winEnd; i++) {
- handles.push(new this.pageHandle({
- collection: collection,
- pageIndex: i
- }));
- }
- }
-
- var controls = this.controls;
- _.each(["back", "rewind", "forward", "fastForward"], function (key) {
- var value = controls[key];
- if (value) {
- var handleCtorOpts = {
- collection: collection,
- title: value.title,
- label: value.label
- };
- handleCtorOpts["is" + key.slice(0, 1).toUpperCase() + key.slice(1)] = true;
- var handle = new this.pageHandle(handleCtorOpts);
- if (key == "rewind" || key == "back") handles.unshift(handle);
- else handles.push(handle);
- }
- }, this);
-
- return handles;
- },
-
- /**
- Render the paginator handles inside an unordered list.
- */
- render: function () {
- this.$el.empty();
-
- if (this.handles) {
- for (var i = 0, l = this.handles.length; i < l; i++) {
- this.handles[i].remove();
- }
- }
-
- var handles = this.handles = this.makeHandles();
-
- var ul = document.createElement("ul");
- for (var i = 0; i < handles.length; i++) {
- ul.appendChild(handles[i].render().el);
- }
-
- this.el.appendChild(ul);
-
- return this;
- }
-
- });
-
-}));
\ No newline at end of file
[09/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/d3-3.5.5.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/d3-3.5.5.js b/htrace-htraced/src/web/lib/js/d3-3.5.5.js
deleted file mode 100644
index 3af706a..0000000
--- a/htrace-htraced/src/web/lib/js/d3-3.5.5.js
+++ /dev/null
@@ -1,9504 +0,0 @@
-!function() {
- var d3 = {
- version: "3.5.5"
- };
- var d3_arraySlice = [].slice, d3_array = function(list) {
- return d3_arraySlice.call(list);
- };
- var d3_document = this.document;
- function d3_documentElement(node) {
- return node && (node.ownerDocument || node.document || node).documentElement;
- }
- function d3_window(node) {
- return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
- }
- if (d3_document) {
- try {
- d3_array(d3_document.documentElement.childNodes)[0].nodeType;
- } catch (e) {
- d3_array = function(list) {
- var i = list.length, array = new Array(i);
- while (i--) array[i] = list[i];
- return array;
- };
- }
- }
- if (!Date.now) Date.now = function() {
- return +new Date();
- };
- if (d3_document) {
- try {
- d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
- } catch (error) {
- var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
- d3_element_prototype.setAttribute = function(name, value) {
- d3_element_setAttribute.call(this, name, value + "");
- };
- d3_element_prototype.setAttributeNS = function(space, local, value) {
- d3_element_setAttributeNS.call(this, space, local, value + "");
- };
- d3_style_prototype.setProperty = function(name, value, priority) {
- d3_style_setProperty.call(this, name, value + "", priority);
- };
- }
- }
- d3.ascending = d3_ascending;
- function d3_ascending(a, b) {
- return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
- }
- d3.descending = function(a, b) {
- return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
- };
- d3.min = function(array, f) {
- var i = -1, n = array.length, a, b;
- if (arguments.length === 1) {
- while (++i < n) if ((b = array[i]) != null && b >= b) {
- a = b;
- break;
- }
- while (++i < n) if ((b = array[i]) != null && a > b) a = b;
- } else {
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
- a = b;
- break;
- }
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
- }
- return a;
- };
- d3.max = function(array, f) {
- var i = -1, n = array.length, a, b;
- if (arguments.length === 1) {
- while (++i < n) if ((b = array[i]) != null && b >= b) {
- a = b;
- break;
- }
- while (++i < n) if ((b = array[i]) != null && b > a) a = b;
- } else {
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
- a = b;
- break;
- }
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
- }
- return a;
- };
- d3.extent = function(array, f) {
- var i = -1, n = array.length, a, b, c;
- if (arguments.length === 1) {
- while (++i < n) if ((b = array[i]) != null && b >= b) {
- a = c = b;
- break;
- }
- while (++i < n) if ((b = array[i]) != null) {
- if (a > b) a = b;
- if (c < b) c = b;
- }
- } else {
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
- a = c = b;
- break;
- }
- while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
- if (a > b) a = b;
- if (c < b) c = b;
- }
- }
- return [ a, c ];
- };
- function d3_number(x) {
- return x === null ? NaN : +x;
- }
- function d3_numeric(x) {
- return !isNaN(x);
- }
- d3.sum = function(array, f) {
- var s = 0, n = array.length, a, i = -1;
- if (arguments.length === 1) {
- while (++i < n) if (d3_numeric(a = +array[i])) s += a;
- } else {
- while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
- }
- return s;
- };
- d3.mean = function(array, f) {
- var s = 0, n = array.length, a, i = -1, j = n;
- if (arguments.length === 1) {
- while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
- } else {
- while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
- }
- if (j) return s / j;
- };
- d3.quantile = function(values, p) {
- var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
- return e ? v + e * (values[h] - v) : v;
- };
- d3.median = function(array, f) {
- var numbers = [], n = array.length, a, i = -1;
- if (arguments.length === 1) {
- while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
- } else {
- while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
- }
- if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
- };
- d3.variance = function(array, f) {
- var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
- if (arguments.length === 1) {
- while (++i < n) {
- if (d3_numeric(a = d3_number(array[i]))) {
- d = a - m;
- m += d / ++j;
- s += d * (a - m);
- }
- }
- } else {
- while (++i < n) {
- if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
- d = a - m;
- m += d / ++j;
- s += d * (a - m);
- }
- }
- }
- if (j > 1) return s / (j - 1);
- };
- d3.deviation = function() {
- var v = d3.variance.apply(this, arguments);
- return v ? Math.sqrt(v) : v;
- };
- function d3_bisector(compare) {
- return {
- left: function(a, x, lo, hi) {
- if (arguments.length < 3) lo = 0;
- if (arguments.length < 4) hi = a.length;
- while (lo < hi) {
- var mid = lo + hi >>> 1;
- if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
- }
- return lo;
- },
- right: function(a, x, lo, hi) {
- if (arguments.length < 3) lo = 0;
- if (arguments.length < 4) hi = a.length;
- while (lo < hi) {
- var mid = lo + hi >>> 1;
- if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
- }
- return lo;
- }
- };
- }
- var d3_bisect = d3_bisector(d3_ascending);
- d3.bisectLeft = d3_bisect.left;
- d3.bisect = d3.bisectRight = d3_bisect.right;
- d3.bisector = function(f) {
- return d3_bisector(f.length === 1 ? function(d, x) {
- return d3_ascending(f(d), x);
- } : f);
- };
- d3.shuffle = function(array, i0, i1) {
- if ((m = arguments.length) < 3) {
- i1 = array.length;
- if (m < 2) i0 = 0;
- }
- var m = i1 - i0, t, i;
- while (m) {
- i = Math.random() * m-- | 0;
- t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
- }
- return array;
- };
- d3.permute = function(array, indexes) {
- var i = indexes.length, permutes = new Array(i);
- while (i--) permutes[i] = array[indexes[i]];
- return permutes;
- };
- d3.pairs = function(array) {
- var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
- while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
- return pairs;
- };
- d3.zip = function() {
- if (!(n = arguments.length)) return [];
- for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
- for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
- zip[j] = arguments[j][i];
- }
- }
- return zips;
- };
- function d3_zipLength(d) {
- return d.length;
- }
- d3.transpose = function(matrix) {
- return d3.zip.apply(d3, matrix);
- };
- d3.keys = function(map) {
- var keys = [];
- for (var key in map) keys.push(key);
- return keys;
- };
- d3.values = function(map) {
- var values = [];
- for (var key in map) values.push(map[key]);
- return values;
- };
- d3.entries = function(map) {
- var entries = [];
- for (var key in map) entries.push({
- key: key,
- value: map[key]
- });
- return entries;
- };
- d3.merge = function(arrays) {
- var n = arrays.length, m, i = -1, j = 0, merged, array;
- while (++i < n) j += arrays[i].length;
- merged = new Array(j);
- while (--n >= 0) {
- array = arrays[n];
- m = array.length;
- while (--m >= 0) {
- merged[--j] = array[m];
- }
- }
- return merged;
- };
- var abs = Math.abs;
- d3.range = function(start, stop, step) {
- if (arguments.length < 3) {
- step = 1;
- if (arguments.length < 2) {
- stop = start;
- start = 0;
- }
- }
- if ((stop - start) / step === Infinity) throw new Error("infinite range");
- var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
- start *= k, stop *= k, step *= k;
- if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
- return range;
- };
- function d3_range_integerScale(x) {
- var k = 1;
- while (x * k % 1) k *= 10;
- return k;
- }
- function d3_class(ctor, properties) {
- for (var key in properties) {
- Object.defineProperty(ctor.prototype, key, {
- value: properties[key],
- enumerable: false
- });
- }
- }
- d3.map = function(object, f) {
- var map = new d3_Map();
- if (object instanceof d3_Map) {
- object.forEach(function(key, value) {
- map.set(key, value);
- });
- } else if (Array.isArray(object)) {
- var i = -1, n = object.length, o;
- if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
- } else {
- for (var key in object) map.set(key, object[key]);
- }
- return map;
- };
- function d3_Map() {
- this._ = Object.create(null);
- }
- var d3_map_proto = "__proto__", d3_map_zero = "\x00";
- d3_class(d3_Map, {
- has: d3_map_has,
- get: function(key) {
- return this._[d3_map_escape(key)];
- },
- set: function(key, value) {
- return this._[d3_map_escape(key)] = value;
- },
- remove: d3_map_remove,
- keys: d3_map_keys,
- values: function() {
- var values = [];
- for (var key in this._) values.push(this._[key]);
- return values;
- },
- entries: function() {
- var entries = [];
- for (var key in this._) entries.push({
- key: d3_map_unescape(key),
- value: this._[key]
- });
- return entries;
- },
- size: d3_map_size,
- empty: d3_map_empty,
- forEach: function(f) {
- for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
- }
- });
- function d3_map_escape(key) {
- return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
- }
- function d3_map_unescape(key) {
- return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
- }
- function d3_map_has(key) {
- return d3_map_escape(key) in this._;
- }
- function d3_map_remove(key) {
- return (key = d3_map_escape(key)) in this._ && delete this._[key];
- }
- function d3_map_keys() {
- var keys = [];
- for (var key in this._) keys.push(d3_map_unescape(key));
- return keys;
- }
- function d3_map_size() {
- var size = 0;
- for (var key in this._) ++size;
- return size;
- }
- function d3_map_empty() {
- for (var key in this._) return false;
- return true;
- }
- d3.nest = function() {
- var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
- function map(mapType, array, depth) {
- if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
- var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
- while (++i < n) {
- if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
- values.push(object);
- } else {
- valuesByKey.set(keyValue, [ object ]);
- }
- }
- if (mapType) {
- object = mapType();
- setter = function(keyValue, values) {
- object.set(keyValue, map(mapType, values, depth));
- };
- } else {
- object = {};
- setter = function(keyValue, values) {
- object[keyValue] = map(mapType, values, depth);
- };
- }
- valuesByKey.forEach(setter);
- return object;
- }
- function entries(map, depth) {
- if (depth >= keys.length) return map;
- var array = [], sortKey = sortKeys[depth++];
- map.forEach(function(key, keyMap) {
- array.push({
- key: key,
- values: entries(keyMap, depth)
- });
- });
- return sortKey ? array.sort(function(a, b) {
- return sortKey(a.key, b.key);
- }) : array;
- }
- nest.map = function(array, mapType) {
- return map(mapType, array, 0);
- };
- nest.entries = function(array) {
- return entries(map(d3.map, array, 0), 0);
- };
- nest.key = function(d) {
- keys.push(d);
- return nest;
- };
- nest.sortKeys = function(order) {
- sortKeys[keys.length - 1] = order;
- return nest;
- };
- nest.sortValues = function(order) {
- sortValues = order;
- return nest;
- };
- nest.rollup = function(f) {
- rollup = f;
- return nest;
- };
- return nest;
- };
- d3.set = function(array) {
- var set = new d3_Set();
- if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
- return set;
- };
- function d3_Set() {
- this._ = Object.create(null);
- }
- d3_class(d3_Set, {
- has: d3_map_has,
- add: function(key) {
- this._[d3_map_escape(key += "")] = true;
- return key;
- },
- remove: d3_map_remove,
- values: d3_map_keys,
- size: d3_map_size,
- empty: d3_map_empty,
- forEach: function(f) {
- for (var key in this._) f.call(this, d3_map_unescape(key));
- }
- });
- d3.behavior = {};
- function d3_identity(d) {
- return d;
- }
- d3.rebind = function(target, source) {
- var i = 1, n = arguments.length, method;
- while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
- return target;
- };
- function d3_rebind(target, source, method) {
- return function() {
- var value = method.apply(source, arguments);
- return value === source ? target : value;
- };
- }
- function d3_vendorSymbol(object, name) {
- if (name in object) return name;
- name = name.charAt(0).toUpperCase() + name.slice(1);
- for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
- var prefixName = d3_vendorPrefixes[i] + name;
- if (prefixName in object) return prefixName;
- }
- }
- var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
- function d3_noop() {}
- d3.dispatch = function() {
- var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
- while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
- return dispatch;
- };
- function d3_dispatch() {}
- d3_dispatch.prototype.on = function(type, listener) {
- var i = type.indexOf("."), name = "";
- if (i >= 0) {
- name = type.slice(i + 1);
- type = type.slice(0, i);
- }
- if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
- if (arguments.length === 2) {
- if (listener == null) for (type in this) {
- if (this.hasOwnProperty(type)) this[type].on(name, null);
- }
- return this;
- }
- };
- function d3_dispatch_event(dispatch) {
- var listeners = [], listenerByName = new d3_Map();
- function event() {
- var z = listeners, i = -1, n = z.length, l;
- while (++i < n) if (l = z[i].on) l.apply(this, arguments);
- return dispatch;
- }
- event.on = function(name, listener) {
- var l = listenerByName.get(name), i;
- if (arguments.length < 2) return l && l.on;
- if (l) {
- l.on = null;
- listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
- listenerByName.remove(name);
- }
- if (listener) listeners.push(listenerByName.set(name, {
- on: listener
- }));
- return dispatch;
- };
- return event;
- }
- d3.event = null;
- function d3_eventPreventDefault() {
- d3.event.preventDefault();
- }
- function d3_eventSource() {
- var e = d3.event, s;
- while (s = e.sourceEvent) e = s;
- return e;
- }
- function d3_eventDispatch(target) {
- var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
- while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
- dispatch.of = function(thiz, argumentz) {
- return function(e1) {
- try {
- var e0 = e1.sourceEvent = d3.event;
- e1.target = target;
- d3.event = e1;
- dispatch[e1.type].apply(thiz, argumentz);
- } finally {
- d3.event = e0;
- }
- };
- };
- return dispatch;
- }
- d3.requote = function(s) {
- return s.replace(d3_requote_re, "\\$&");
- };
- var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
- var d3_subclass = {}.__proto__ ? function(object, prototype) {
- object.__proto__ = prototype;
- } : function(object, prototype) {
- for (var property in prototype) object[property] = prototype[property];
- };
- function d3_selection(groups) {
- d3_subclass(groups, d3_selectionPrototype);
- return groups;
- }
- var d3_select = function(s, n) {
- return n.querySelector(s);
- }, d3_selectAll = function(s, n) {
- return n.querySelectorAll(s);
- }, d3_selectMatches = function(n, s) {
- var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
- d3_selectMatches = function(n, s) {
- return d3_selectMatcher.call(n, s);
- };
- return d3_selectMatches(n, s);
- };
- if (typeof Sizzle === "function") {
- d3_select = function(s, n) {
- return Sizzle(s, n)[0] || null;
- };
- d3_selectAll = Sizzle;
- d3_selectMatches = Sizzle.matchesSelector;
- }
- d3.selection = function() {
- return d3.select(d3_document.documentElement);
- };
- var d3_selectionPrototype = d3.selection.prototype = [];
- d3_selectionPrototype.select = function(selector) {
- var subgroups = [], subgroup, subnode, group, node;
- selector = d3_selection_selector(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- subgroups.push(subgroup = []);
- subgroup.parentNode = (group = this[j]).parentNode;
- for (var i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroup.push(subnode = selector.call(node, node.__data__, i, j));
- if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selector(selector) {
- return typeof selector === "function" ? selector : function() {
- return d3_select(selector, this);
- };
- }
- d3_selectionPrototype.selectAll = function(selector) {
- var subgroups = [], subgroup, node;
- selector = d3_selection_selectorAll(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
- subgroup.parentNode = node;
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selectorAll(selector) {
- return typeof selector === "function" ? selector : function() {
- return d3_selectAll(selector, this);
- };
- }
- var d3_nsPrefix = {
- svg: "http://www.w3.org/2000/svg",
- xhtml: "http://www.w3.org/1999/xhtml",
- xlink: "http://www.w3.org/1999/xlink",
- xml: "http://www.w3.org/XML/1998/namespace",
- xmlns: "http://www.w3.org/2000/xmlns/"
- };
- d3.ns = {
- prefix: d3_nsPrefix,
- qualify: function(name) {
- var i = name.indexOf(":"), prefix = name;
- if (i >= 0) {
- prefix = name.slice(0, i);
- name = name.slice(i + 1);
- }
- return d3_nsPrefix.hasOwnProperty(prefix) ? {
- space: d3_nsPrefix[prefix],
- local: name
- } : name;
- }
- };
- d3_selectionPrototype.attr = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") {
- var node = this.node();
- name = d3.ns.qualify(name);
- return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
- }
- for (value in name) this.each(d3_selection_attr(value, name[value]));
- return this;
- }
- return this.each(d3_selection_attr(name, value));
- };
- function d3_selection_attr(name, value) {
- name = d3.ns.qualify(name);
- function attrNull() {
- this.removeAttribute(name);
- }
- function attrNullNS() {
- this.removeAttributeNS(name.space, name.local);
- }
- function attrConstant() {
- this.setAttribute(name, value);
- }
- function attrConstantNS() {
- this.setAttributeNS(name.space, name.local, value);
- }
- function attrFunction() {
- var x = value.apply(this, arguments);
- if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
- }
- function attrFunctionNS() {
- var x = value.apply(this, arguments);
- if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
- }
- return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
- }
- function d3_collapse(s) {
- return s.trim().replace(/\s+/g, " ");
- }
- d3_selectionPrototype.classed = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") {
- var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
- if (value = node.classList) {
- while (++i < n) if (!value.contains(name[i])) return false;
- } else {
- value = node.getAttribute("class");
- while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
- }
- return true;
- }
- for (value in name) this.each(d3_selection_classed(value, name[value]));
- return this;
- }
- return this.each(d3_selection_classed(name, value));
- };
- function d3_selection_classedRe(name) {
- return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
- }
- function d3_selection_classes(name) {
- return (name + "").trim().split(/^|\s+/);
- }
- function d3_selection_classed(name, value) {
- name = d3_selection_classes(name).map(d3_selection_classedName);
- var n = name.length;
- function classedConstant() {
- var i = -1;
- while (++i < n) name[i](this, value);
- }
- function classedFunction() {
- var i = -1, x = value.apply(this, arguments);
- while (++i < n) name[i](this, x);
- }
- return typeof value === "function" ? classedFunction : classedConstant;
- }
- function d3_selection_classedName(name) {
- var re = d3_selection_classedRe(name);
- return function(node, value) {
- if (c = node.classList) return value ? c.add(name) : c.remove(name);
- var c = node.getAttribute("class") || "";
- if (value) {
- re.lastIndex = 0;
- if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
- } else {
- node.setAttribute("class", d3_collapse(c.replace(re, " ")));
- }
- };
- }
- d3_selectionPrototype.style = function(name, value, priority) {
- var n = arguments.length;
- if (n < 3) {
- if (typeof name !== "string") {
- if (n < 2) value = "";
- for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
- return this;
- }
- if (n < 2) {
- var node = this.node();
- return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
- }
- priority = "";
- }
- return this.each(d3_selection_style(name, value, priority));
- };
- function d3_selection_style(name, value, priority) {
- function styleNull() {
- this.style.removeProperty(name);
- }
- function styleConstant() {
- this.style.setProperty(name, value, priority);
- }
- function styleFunction() {
- var x = value.apply(this, arguments);
- if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
- }
- return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
- }
- d3_selectionPrototype.property = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") return this.node()[name];
- for (value in name) this.each(d3_selection_property(value, name[value]));
- return this;
- }
- return this.each(d3_selection_property(name, value));
- };
- function d3_selection_property(name, value) {
- function propertyNull() {
- delete this[name];
- }
- function propertyConstant() {
- this[name] = value;
- }
- function propertyFunction() {
- var x = value.apply(this, arguments);
- if (x == null) delete this[name]; else this[name] = x;
- }
- return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
- }
- d3_selectionPrototype.text = function(value) {
- return arguments.length ? this.each(typeof value === "function" ? function() {
- var v = value.apply(this, arguments);
- this.textContent = v == null ? "" : v;
- } : value == null ? function() {
- this.textContent = "";
- } : function() {
- this.textContent = value;
- }) : this.node().textContent;
- };
- d3_selectionPrototype.html = function(value) {
- return arguments.length ? this.each(typeof value === "function" ? function() {
- var v = value.apply(this, arguments);
- this.innerHTML = v == null ? "" : v;
- } : value == null ? function() {
- this.innerHTML = "";
- } : function() {
- this.innerHTML = value;
- }) : this.node().innerHTML;
- };
- d3_selectionPrototype.append = function(name) {
- name = d3_selection_creator(name);
- return this.select(function() {
- return this.appendChild(name.apply(this, arguments));
- });
- };
- function d3_selection_creator(name) {
- function create() {
- var document = this.ownerDocument, namespace = this.namespaceURI;
- return namespace ? document.createElementNS(namespace, name) : document.createElement(name);
- }
- function createNS() {
- return this.ownerDocument.createElementNS(name.space, name.local);
- }
- return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
- }
- d3_selectionPrototype.insert = function(name, before) {
- name = d3_selection_creator(name);
- before = d3_selection_selector(before);
- return this.select(function() {
- return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
- });
- };
- d3_selectionPrototype.remove = function() {
- return this.each(d3_selectionRemove);
- };
- function d3_selectionRemove() {
- var parent = this.parentNode;
- if (parent) parent.removeChild(this);
- }
- d3_selectionPrototype.data = function(value, key) {
- var i = -1, n = this.length, group, node;
- if (!arguments.length) {
- value = new Array(n = (group = this[0]).length);
- while (++i < n) {
- if (node = group[i]) {
- value[i] = node.__data__;
- }
- }
- return value;
- }
- function bind(group, groupData) {
- var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
- if (key) {
- var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
- for (i = -1; ++i < n; ) {
- if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
- exitNodes[i] = node;
- } else {
- nodeByKeyValue.set(keyValue, node);
- }
- keyValues[i] = keyValue;
- }
- for (i = -1; ++i < m; ) {
- if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
- enterNodes[i] = d3_selection_dataNode(nodeData);
- } else if (node !== true) {
- updateNodes[i] = node;
- node.__data__ = nodeData;
- }
- nodeByKeyValue.set(keyValue, true);
- }
- for (i = -1; ++i < n; ) {
- if (nodeByKeyValue.get(keyValues[i]) !== true) {
- exitNodes[i] = group[i];
- }
- }
- } else {
- for (i = -1; ++i < n0; ) {
- node = group[i];
- nodeData = groupData[i];
- if (node) {
- node.__data__ = nodeData;
- updateNodes[i] = node;
- } else {
- enterNodes[i] = d3_selection_dataNode(nodeData);
- }
- }
- for (;i < m; ++i) {
- enterNodes[i] = d3_selection_dataNode(groupData[i]);
- }
- for (;i < n; ++i) {
- exitNodes[i] = group[i];
- }
- }
- enterNodes.update = updateNodes;
- enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
- enter.push(enterNodes);
- update.push(updateNodes);
- exit.push(exitNodes);
- }
- var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
- if (typeof value === "function") {
- while (++i < n) {
- bind(group = this[i], value.call(group, group.parentNode.__data__, i));
- }
- } else {
- while (++i < n) {
- bind(group = this[i], value);
- }
- }
- update.enter = function() {
- return enter;
- };
- update.exit = function() {
- return exit;
- };
- return update;
- };
- function d3_selection_dataNode(data) {
- return {
- __data__: data
- };
- }
- d3_selectionPrototype.datum = function(value) {
- return arguments.length ? this.property("__data__", value) : this.property("__data__");
- };
- d3_selectionPrototype.filter = function(filter) {
- var subgroups = [], subgroup, group, node;
- if (typeof filter !== "function") filter = d3_selection_filter(filter);
- for (var j = 0, m = this.length; j < m; j++) {
- subgroups.push(subgroup = []);
- subgroup.parentNode = (group = this[j]).parentNode;
- for (var i = 0, n = group.length; i < n; i++) {
- if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
- subgroup.push(node);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_filter(selector) {
- return function() {
- return d3_selectMatches(this, selector);
- };
- }
- d3_selectionPrototype.order = function() {
- for (var j = -1, m = this.length; ++j < m; ) {
- for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
- if (node = group[i]) {
- if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
- next = node;
- }
- }
- }
- return this;
- };
- d3_selectionPrototype.sort = function(comparator) {
- comparator = d3_selection_sortComparator.apply(this, arguments);
- for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
- return this.order();
- };
- function d3_selection_sortComparator(comparator) {
- if (!arguments.length) comparator = d3_ascending;
- return function(a, b) {
- return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
- };
- }
- d3_selectionPrototype.each = function(callback) {
- return d3_selection_each(this, function(node, i, j) {
- callback.call(node, node.__data__, i, j);
- });
- };
- function d3_selection_each(groups, callback) {
- for (var j = 0, m = groups.length; j < m; j++) {
- for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
- if (node = group[i]) callback(node, i, j);
- }
- }
- return groups;
- }
- d3_selectionPrototype.call = function(callback) {
- var args = d3_array(arguments);
- callback.apply(args[0] = this, args);
- return this;
- };
- d3_selectionPrototype.empty = function() {
- return !this.node();
- };
- d3_selectionPrototype.node = function() {
- for (var j = 0, m = this.length; j < m; j++) {
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
- var node = group[i];
- if (node) return node;
- }
- }
- return null;
- };
- d3_selectionPrototype.size = function() {
- var n = 0;
- d3_selection_each(this, function() {
- ++n;
- });
- return n;
- };
- function d3_selection_enter(selection) {
- d3_subclass(selection, d3_selection_enterPrototype);
- return selection;
- }
- var d3_selection_enterPrototype = [];
- d3.selection.enter = d3_selection_enter;
- d3.selection.enter.prototype = d3_selection_enterPrototype;
- d3_selection_enterPrototype.append = d3_selectionPrototype.append;
- d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
- d3_selection_enterPrototype.node = d3_selectionPrototype.node;
- d3_selection_enterPrototype.call = d3_selectionPrototype.call;
- d3_selection_enterPrototype.size = d3_selectionPrototype.size;
- d3_selection_enterPrototype.select = function(selector) {
- var subgroups = [], subgroup, subnode, upgroup, group, node;
- for (var j = -1, m = this.length; ++j < m; ) {
- upgroup = (group = this[j]).update;
- subgroups.push(subgroup = []);
- subgroup.parentNode = group.parentNode;
- for (var i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
- subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- d3_selection_enterPrototype.insert = function(name, before) {
- if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
- return d3_selectionPrototype.insert.call(this, name, before);
- };
- function d3_selection_enterInsertBefore(enter) {
- var i0, j0;
- return function(d, i, j) {
- var group = enter[j].update, n = group.length, node;
- if (j != j0) j0 = j, i0 = 0;
- if (i >= i0) i0 = i + 1;
- while (!(node = group[i0]) && ++i0 < n) ;
- return node;
- };
- }
- d3.select = function(node) {
- var group;
- if (typeof node === "string") {
- group = [ d3_select(node, d3_document) ];
- group.parentNode = d3_document.documentElement;
- } else {
- group = [ node ];
- group.parentNode = d3_documentElement(node);
- }
- return d3_selection([ group ]);
- };
- d3.selectAll = function(nodes) {
- var group;
- if (typeof nodes === "string") {
- group = d3_array(d3_selectAll(nodes, d3_document));
- group.parentNode = d3_document.documentElement;
- } else {
- group = nodes;
- group.parentNode = null;
- }
- return d3_selection([ group ]);
- };
- d3_selectionPrototype.on = function(type, listener, capture) {
- var n = arguments.length;
- if (n < 3) {
- if (typeof type !== "string") {
- if (n < 2) listener = false;
- for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
- return this;
- }
- if (n < 2) return (n = this.node()["__on" + type]) && n._;
- capture = false;
- }
- return this.each(d3_selection_on(type, listener, capture));
- };
- function d3_selection_on(type, listener, capture) {
- var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
- if (i > 0) type = type.slice(0, i);
- var filter = d3_selection_onFilters.get(type);
- if (filter) type = filter, wrap = d3_selection_onFilter;
- function onRemove() {
- var l = this[name];
- if (l) {
- this.removeEventListener(type, l, l.$);
- delete this[name];
- }
- }
- function onAdd() {
- var l = wrap(listener, d3_array(arguments));
- onRemove.call(this);
- this.addEventListener(type, this[name] = l, l.$ = capture);
- l._ = listener;
- }
- function removeAll() {
- var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
- for (var name in this) {
- if (match = name.match(re)) {
- var l = this[name];
- this.removeEventListener(match[1], l, l.$);
- delete this[name];
- }
- }
- }
- return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
- }
- var d3_selection_onFilters = d3.map({
- mouseenter: "mouseover",
- mouseleave: "mouseout"
- });
- if (d3_document) {
- d3_selection_onFilters.forEach(function(k) {
- if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
- });
- }
- function d3_selection_onListener(listener, argumentz) {
- return function(e) {
- var o = d3.event;
- d3.event = e;
- argumentz[0] = this.__data__;
- try {
- listener.apply(this, argumentz);
- } finally {
- d3.event = o;
- }
- };
- }
- function d3_selection_onFilter(listener, argumentz) {
- var l = d3_selection_onListener(listener, argumentz);
- return function(e) {
- var target = this, related = e.relatedTarget;
- if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
- l.call(target, e);
- }
- };
- }
- var d3_event_dragSelect, d3_event_dragId = 0;
- function d3_event_dragSuppress(node) {
- var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
- if (d3_event_dragSelect == null) {
- d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
- }
- if (d3_event_dragSelect) {
- var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
- style[d3_event_dragSelect] = "none";
- }
- return function(suppressClick) {
- w.on(name, null);
- if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
- if (suppressClick) {
- var off = function() {
- w.on(click, null);
- };
- w.on(click, function() {
- d3_eventPreventDefault();
- off();
- }, true);
- setTimeout(off, 0);
- }
- };
- }
- d3.mouse = function(container) {
- return d3_mousePoint(container, d3_eventSource());
- };
- var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
- function d3_mousePoint(container, e) {
- if (e.changedTouches) e = e.changedTouches[0];
- var svg = container.ownerSVGElement || container;
- if (svg.createSVGPoint) {
- var point = svg.createSVGPoint();
- if (d3_mouse_bug44083 < 0) {
- var window = d3_window(container);
- if (window.scrollX || window.scrollY) {
- svg = d3.select("body").append("svg").style({
- position: "absolute",
- top: 0,
- left: 0,
- margin: 0,
- padding: 0,
- border: "none"
- }, "important");
- var ctm = svg[0][0].getScreenCTM();
- d3_mouse_bug44083 = !(ctm.f || ctm.e);
- svg.remove();
- }
- }
- if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX,
- point.y = e.clientY;
- point = point.matrixTransform(container.getScreenCTM().inverse());
- return [ point.x, point.y ];
- }
- var rect = container.getBoundingClientRect();
- return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
- }
- d3.touch = function(container, touches, identifier) {
- if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
- if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
- if ((touch = touches[i]).identifier === identifier) {
- return d3_mousePoint(container, touch);
- }
- }
- };
- d3.behavior.drag = function() {
- var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
- function drag() {
- this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
- }
- function dragstart(id, position, subject, move, end) {
- return function() {
- var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
- if (origin) {
- dragOffset = origin.apply(that, arguments);
- dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
- } else {
- dragOffset = [ 0, 0 ];
- }
- dispatch({
- type: "dragstart"
- });
- function moved() {
- var position1 = position(parent, dragId), dx, dy;
- if (!position1) return;
- dx = position1[0] - position0[0];
- dy = position1[1] - position0[1];
- dragged |= dx | dy;
- position0 = position1;
- dispatch({
- type: "drag",
- x: position1[0] + dragOffset[0],
- y: position1[1] + dragOffset[1],
- dx: dx,
- dy: dy
- });
- }
- function ended() {
- if (!position(parent, dragId)) return;
- dragSubject.on(move + dragName, null).on(end + dragName, null);
- dragRestore(dragged && d3.event.target === target);
- dispatch({
- type: "dragend"
- });
- }
- };
- }
- drag.origin = function(x) {
- if (!arguments.length) return origin;
- origin = x;
- return drag;
- };
- return d3.rebind(drag, event, "on");
- };
- function d3_behavior_dragTouchId() {
- return d3.event.changedTouches[0].identifier;
- }
- d3.touches = function(container, touches) {
- if (arguments.length < 2) touches = d3_eventSource().touches;
- return touches ? d3_array(touches).map(function(touch) {
- var point = d3_mousePoint(container, touch);
- point.identifier = touch.identifier;
- return point;
- }) : [];
- };
- var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
- function d3_sgn(x) {
- return x > 0 ? 1 : x < 0 ? -1 : 0;
- }
- function d3_cross2d(a, b, c) {
- return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
- }
- function d3_acos(x) {
- return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
- }
- function d3_asin(x) {
- return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
- }
- function d3_sinh(x) {
- return ((x = Math.exp(x)) - 1 / x) / 2;
- }
- function d3_cosh(x) {
- return ((x = Math.exp(x)) + 1 / x) / 2;
- }
- function d3_tanh(x) {
- return ((x = Math.exp(2 * x)) - 1) / (x + 1);
- }
- function d3_haversin(x) {
- return (x = Math.sin(x / 2)) * x;
- }
- var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
- d3.interpolateZoom = function(p0, p1) {
- var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
- var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
- function interpolate(t) {
- var s = t * S;
- if (dr) {
- var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
- return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
- }
- return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
- }
- interpolate.duration = S * 1e3;
- return interpolate;
- };
- d3.behavior.zoom = function() {
- var view = {
- x: 0,
- y: 0,
- k: 1
- }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
- if (!d3_behavior_zoomWheel) {
- d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
- return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
- }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
- return d3.event.wheelDelta;
- }, "mousewheel") : (d3_behavior_zoomDelta = function() {
- return -d3.event.detail;
- }, "MozMousePixelScroll");
- }
- function zoom(g) {
- g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
- }
- zoom.event = function(g) {
- g.each(function() {
- var dispatch = event.of(this, arguments), view1 = view;
- if (d3_transitionInheritId) {
- d3.select(this).transition().each("start.zoom", function() {
- view = this.__chart__ || {
- x: 0,
- y: 0,
- k: 1
- };
- zoomstarted(dispatch);
- }).tween("zoom:zoom", function() {
- var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
- return function(t) {
- var l = i(t), k = dx / l[2];
- this.__chart__ = view = {
- x: cx - l[0] * k,
- y: cy - l[1] * k,
- k: k
- };
- zoomed(dispatch);
- };
- }).each("interrupt.zoom", function() {
- zoomended(dispatch);
- }).each("end.zoom", function() {
- zoomended(dispatch);
- });
- } else {
- this.__chart__ = view;
- zoomstarted(dispatch);
- zoomed(dispatch);
- zoomended(dispatch);
- }
- });
- };
- zoom.translate = function(_) {
- if (!arguments.length) return [ view.x, view.y ];
- view = {
- x: +_[0],
- y: +_[1],
- k: view.k
- };
- rescale();
- return zoom;
- };
- zoom.scale = function(_) {
- if (!arguments.length) return view.k;
- view = {
- x: view.x,
- y: view.y,
- k: +_
- };
- rescale();
- return zoom;
- };
- zoom.scaleExtent = function(_) {
- if (!arguments.length) return scaleExtent;
- scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
- return zoom;
- };
- zoom.center = function(_) {
- if (!arguments.length) return center;
- center = _ && [ +_[0], +_[1] ];
- return zoom;
- };
- zoom.size = function(_) {
- if (!arguments.length) return size;
- size = _ && [ +_[0], +_[1] ];
- return zoom;
- };
- zoom.duration = function(_) {
- if (!arguments.length) return duration;
- duration = +_;
- return zoom;
- };
- zoom.x = function(z) {
- if (!arguments.length) return x1;
- x1 = z;
- x0 = z.copy();
- view = {
- x: 0,
- y: 0,
- k: 1
- };
- return zoom;
- };
- zoom.y = function(z) {
- if (!arguments.length) return y1;
- y1 = z;
- y0 = z.copy();
- view = {
- x: 0,
- y: 0,
- k: 1
- };
- return zoom;
- };
- function location(p) {
- return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
- }
- function point(l) {
- return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
- }
- function scaleTo(s) {
- view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
- }
- function translateTo(p, l) {
- l = point(l);
- view.x += p[0] - l[0];
- view.y += p[1] - l[1];
- }
- function zoomTo(that, p, l, k) {
- that.__chart__ = {
- x: view.x,
- y: view.y,
- k: view.k
- };
- scaleTo(Math.pow(2, k));
- translateTo(center0 = p, l);
- that = d3.select(that);
- if (duration > 0) that = that.transition().duration(duration);
- that.call(zoom.event);
- }
- function rescale() {
- if (x1) x1.domain(x0.range().map(function(x) {
- return (x - view.x) / view.k;
- }).map(x0.invert));
- if (y1) y1.domain(y0.range().map(function(y) {
- return (y - view.y) / view.k;
- }).map(y0.invert));
- }
- function zoomstarted(dispatch) {
- if (!zooming++) dispatch({
- type: "zoomstart"
- });
- }
- function zoomed(dispatch) {
- rescale();
- dispatch({
- type: "zoom",
- scale: view.k,
- translate: [ view.x, view.y ]
- });
- }
- function zoomended(dispatch) {
- if (!--zooming) dispatch({
- type: "zoomend"
- });
- center0 = null;
- }
- function mousedowned() {
- var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
- d3_selection_interrupt.call(that);
- zoomstarted(dispatch);
- function moved() {
- dragged = 1;
- translateTo(d3.mouse(that), location0);
- zoomed(dispatch);
- }
- function ended() {
- subject.on(mousemove, null).on(mouseup, null);
- dragRestore(dragged && d3.event.target === target);
- zoomended(dispatch);
- }
- }
- function touchstarted() {
- var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
- started();
- zoomstarted(dispatch);
- subject.on(mousedown, null).on(touchstart, started);
- function relocate() {
- var touches = d3.touches(that);
- scale0 = view.k;
- touches.forEach(function(t) {
- if (t.identifier in locations0) locations0[t.identifier] = location(t);
- });
- return touches;
- }
- function started() {
- var target = d3.event.target;
- d3.select(target).on(touchmove, moved).on(touchend, ended);
- targets.push(target);
- var changed = d3.event.changedTouches;
- for (var i = 0, n = changed.length; i < n; ++i) {
- locations0[changed[i].identifier] = null;
- }
- var touches = relocate(), now = Date.now();
- if (touches.length === 1) {
- if (now - touchtime < 500) {
- var p = touches[0];
- zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
- d3_eventPreventDefault();
- }
- touchtime = now;
- } else if (touches.length > 1) {
- var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
- distance0 = dx * dx + dy * dy;
- }
- }
- function moved() {
- var touches = d3.touches(that), p0, l0, p1, l1;
- d3_selection_interrupt.call(that);
- for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
- p1 = touches[i];
- if (l1 = locations0[p1.identifier]) {
- if (l0) break;
- p0 = p1, l0 = l1;
- }
- }
- if (l1) {
- var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
- p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
- l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
- scaleTo(scale1 * scale0);
- }
- touchtime = null;
- translateTo(p0, l0);
- zoomed(dispatch);
- }
- function ended() {
- if (d3.event.touches.length) {
- var changed = d3.event.changedTouches;
- for (var i = 0, n = changed.length; i < n; ++i) {
- delete locations0[changed[i].identifier];
- }
- for (var identifier in locations0) {
- return void relocate();
- }
- }
- d3.selectAll(targets).on(zoomName, null);
- subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
- dragRestore();
- zoomended(dispatch);
- }
- }
- function mousewheeled() {
- var dispatch = event.of(this, arguments);
- if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)),
- d3_selection_interrupt.call(this), zoomstarted(dispatch);
- mousewheelTimer = setTimeout(function() {
- mousewheelTimer = null;
- zoomended(dispatch);
- }, 50);
- d3_eventPreventDefault();
- scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
- translateTo(center0, translate0);
- zoomed(dispatch);
- }
- function dblclicked() {
- var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
- zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
- }
- return d3.rebind(zoom, event, "on");
- };
- var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
- d3.color = d3_color;
- function d3_color() {}
- d3_color.prototype.toString = function() {
- return this.rgb() + "";
- };
- d3.hsl = d3_hsl;
- function d3_hsl(h, s, l) {
- return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
- }
- var d3_hslPrototype = d3_hsl.prototype = new d3_color();
- d3_hslPrototype.brighter = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return new d3_hsl(this.h, this.s, this.l / k);
- };
- d3_hslPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return new d3_hsl(this.h, this.s, k * this.l);
- };
- d3_hslPrototype.rgb = function() {
- return d3_hsl_rgb(this.h, this.s, this.l);
- };
- function d3_hsl_rgb(h, s, l) {
- var m1, m2;
- h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
- s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
- l = l < 0 ? 0 : l > 1 ? 1 : l;
- m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
- m1 = 2 * l - m2;
- function v(h) {
- if (h > 360) h -= 360; else if (h < 0) h += 360;
- if (h < 60) return m1 + (m2 - m1) * h / 60;
- if (h < 180) return m2;
- if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
- return m1;
- }
- function vv(h) {
- return Math.round(v(h) * 255);
- }
- return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
- }
- d3.hcl = d3_hcl;
- function d3_hcl(h, c, l) {
- return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
- }
- var d3_hclPrototype = d3_hcl.prototype = new d3_color();
- d3_hclPrototype.brighter = function(k) {
- return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
- };
- d3_hclPrototype.darker = function(k) {
- return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
- };
- d3_hclPrototype.rgb = function() {
- return d3_hcl_lab(this.h, this.c, this.l).rgb();
- };
- function d3_hcl_lab(h, c, l) {
- if (isNaN(h)) h = 0;
- if (isNaN(c)) c = 0;
- return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
- }
- d3.lab = d3_lab;
- function d3_lab(l, a, b) {
- return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
- }
- var d3_lab_K = 18;
- var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
- var d3_labPrototype = d3_lab.prototype = new d3_color();
- d3_labPrototype.brighter = function(k) {
- return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
- };
- d3_labPrototype.darker = function(k) {
- return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
- };
- d3_labPrototype.rgb = function() {
- return d3_lab_rgb(this.l, this.a, this.b);
- };
- function d3_lab_rgb(l, a, b) {
- var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
- x = d3_lab_xyz(x) * d3_lab_X;
- y = d3_lab_xyz(y) * d3_lab_Y;
- z = d3_lab_xyz(z) * d3_lab_Z;
- return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
- }
- function d3_lab_hcl(l, a, b) {
- return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
- }
- function d3_lab_xyz(x) {
- return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
- }
- function d3_xyz_lab(x) {
- return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
- }
- function d3_xyz_rgb(r) {
- return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
- }
- d3.rgb = d3_rgb;
- function d3_rgb(r, g, b) {
- return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
- }
- function d3_rgbNumber(value) {
- return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
- }
- function d3_rgbString(value) {
- return d3_rgbNumber(value) + "";
- }
- var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
- d3_rgbPrototype.brighter = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- var r = this.r, g = this.g, b = this.b, i = 30;
- if (!r && !g && !b) return new d3_rgb(i, i, i);
- if (r && r < i) r = i;
- if (g && g < i) g = i;
- if (b && b < i) b = i;
- return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
- };
- d3_rgbPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return new d3_rgb(k * this.r, k * this.g, k * this.b);
- };
- d3_rgbPrototype.hsl = function() {
- return d3_rgb_hsl(this.r, this.g, this.b);
- };
- d3_rgbPrototype.toString = function() {
- return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
- };
- function d3_rgb_hex(v) {
- return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
- }
- function d3_rgb_parse(format, rgb, hsl) {
- var r = 0, g = 0, b = 0, m1, m2, color;
- m1 = /([a-z]+)\((.*)\)/i.exec(format);
- if (m1) {
- m2 = m1[2].split(",");
- switch (m1[1]) {
- case "hsl":
- {
- return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
- }
-
- case "rgb":
- {
- return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
- }
- }
- }
- if (color = d3_rgb_names.get(format.toLowerCase())) {
- return rgb(color.r, color.g, color.b);
- }
- if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
- if (format.length === 4) {
- r = (color & 3840) >> 4;
- r = r >> 4 | r;
- g = color & 240;
- g = g >> 4 | g;
- b = color & 15;
- b = b << 4 | b;
- } else if (format.length === 7) {
- r = (color & 16711680) >> 16;
- g = (color & 65280) >> 8;
- b = color & 255;
- }
- }
- return rgb(r, g, b);
- }
- function d3_rgb_hsl(r, g, b) {
- var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
- if (d) {
- s = l < .5 ? d / (max + min) : d / (2 - max - min);
- if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
- h *= 60;
- } else {
- h = NaN;
- s = l > 0 && l < 1 ? 0 : h;
- }
- return new d3_hsl(h, s, l);
- }
- function d3_rgb_lab(r, g, b) {
- r = d3_rgb_xyz(r);
- g = d3_rgb_xyz(g);
- b = d3_rgb_xyz(b);
- var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
- return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
- }
- function d3_rgb_xyz(r) {
- return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
- }
- function d3_rgb_parseNumber(c) {
- var f = parseFloat(c);
- return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
- }
- var d3_rgb_names = d3.map({
- aliceblue: 15792383,
- antiquewhite: 16444375,
- aqua: 65535,
- aquamarine: 8388564,
- azure: 15794175,
- beige: 16119260,
- bisque: 16770244,
- black: 0,
- blanchedalmond: 16772045,
- blue: 255,
- blueviolet: 9055202,
- brown: 10824234,
- burlywood: 14596231,
- cadetblue: 6266528,
- chartreuse: 8388352,
- chocolate: 13789470,
- coral: 16744272,
- cornflowerblue: 6591981,
- cornsilk: 16775388,
- crimson: 14423100,
- cyan: 65535,
- darkblue: 139,
- darkcyan: 35723,
- darkgoldenrod: 12092939,
- darkgray: 11119017,
- darkgreen: 25600,
- darkgrey: 11119017,
- darkkhaki: 12433259,
- darkmagenta: 9109643,
- darkolivegreen: 5597999,
- darkorange: 16747520,
- darkorchid: 10040012,
- darkred: 9109504,
- darksalmon: 15308410,
- darkseagreen: 9419919,
- darkslateblue: 4734347,
- darkslategray: 3100495,
- darkslategrey: 3100495,
- darkturquoise: 52945,
- darkviolet: 9699539,
- deeppink: 16716947,
- deepskyblue: 49151,
- dimgray: 6908265,
- dimgrey: 6908265,
- dodgerblue: 2003199,
- firebrick: 11674146,
- floralwhite: 16775920,
- forestgreen: 2263842,
- fuchsia: 16711935,
- gainsboro: 14474460,
- ghostwhite: 16316671,
- gold: 16766720,
- goldenrod: 14329120,
- gray: 8421504,
- green: 32768,
- greenyellow: 11403055,
- grey: 8421504,
- honeydew: 15794160,
- hotpink: 16738740,
- indianred: 13458524,
- indigo: 4915330,
- ivory: 16777200,
- khaki: 15787660,
- lavender: 15132410,
- lavenderblush: 16773365,
- lawngreen: 8190976,
- lemonchiffon: 16775885,
- lightblue: 11393254,
- lightcoral: 15761536,
- lightcyan: 14745599,
- lightgoldenrodyellow: 16448210,
- lightgray: 13882323,
- lightgreen: 9498256,
- lightgrey: 13882323,
- lightpink: 16758465,
- lightsalmon: 16752762,
- lightseagreen: 2142890,
- lightskyblue: 8900346,
- lightslategray: 7833753,
- lightslategrey: 7833753,
- lightsteelblue: 11584734,
- lightyellow: 16777184,
- lime: 65280,
- limegreen: 3329330,
- linen: 16445670,
- magenta: 16711935,
- maroon: 8388608,
- mediumaquamarine: 6737322,
- mediumblue: 205,
- mediumorchid: 12211667,
- mediumpurple: 9662683,
- mediumseagreen: 3978097,
- mediumslateblue: 8087790,
- mediumspringgreen: 64154,
- mediumturquoise: 4772300,
- mediumvioletred: 13047173,
- midnightblue: 1644912,
- mintcream: 16121850,
- mistyrose: 16770273,
- moccasin: 16770229,
- navajowhite: 16768685,
- navy: 128,
- oldlace: 16643558,
- olive: 8421376,
- olivedrab: 7048739,
- orange: 16753920,
- orangered: 16729344,
- orchid: 14315734,
- palegoldenrod: 15657130,
- palegreen: 10025880,
- paleturquoise: 11529966,
- palevioletred: 14381203,
- papayawhip: 16773077,
- peachpuff: 16767673,
- peru: 13468991,
- pink: 16761035,
- plum: 14524637,
- powderblue: 11591910,
- purple: 8388736,
- rebeccapurple: 6697881,
- red: 16711680,
- rosybrown: 12357519,
- royalblue: 4286945,
- saddlebrown: 9127187,
- salmon: 16416882,
- sandybrown: 16032864,
- seagreen: 3050327,
- seashell: 16774638,
- sienna: 10506797,
- silver: 12632256,
- skyblue: 8900331,
- slateblue: 6970061,
- slategray: 7372944,
- slategrey: 7372944,
- snow: 16775930,
- springgreen: 65407,
- steelblue: 4620980,
- tan: 13808780,
- teal: 32896,
- thistle: 14204888,
- tomato: 16737095,
- turquoise: 4251856,
- violet: 15631086,
- wheat: 16113331,
- white: 16777215,
- whitesmoke: 16119285,
- yellow: 16776960,
- yellowgreen: 10145074
- });
- d3_rgb_names.forEach(function(key, value) {
- d3_rgb_names.set(key, d3_rgbNumber(value));
- });
- function d3_functor(v) {
- return typeof v === "function" ? v : function() {
- return v;
- };
- }
- d3.functor = d3_functor;
- d3.xhr = d3_xhrType(d3_identity);
- function d3_xhrType(response) {
- return function(url, mimeType, callback) {
- if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
- mimeType = null;
- return d3_xhr(url, mimeType, response, callback);
- };
- }
- function d3_xhr(url, mimeType, response, callback) {
- var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
- if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
- "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
- request.readyState > 3 && respond();
- };
- function respond() {
- var status = request.status, result;
- if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
- try {
- result = response.call(xhr, request);
- } catch (e) {
- dispatch.error.call(xhr, e);
- return;
- }
- dispatch.load.call(xhr, result);
- } else {
- dispatch.error.call(xhr, request);
- }
- }
- request.onprogress = function(event) {
- var o = d3.event;
- d3.event = event;
- try {
- dispatch.progress.call(xhr, request);
- } finally {
- d3.event = o;
- }
- };
- xhr.header = function(name, value) {
- name = (name + "").toLowerCase();
- if (arguments.length < 2) return headers[name];
- if (value == null) delete headers[name]; else headers[name] = value + "";
- return xhr;
- };
- xhr.mimeType = function(value) {
- if (!arguments.length) return mimeType;
- mimeType = value == null ? null : value + "";
- return xhr;
- };
- xhr.responseType = function(value) {
- if (!arguments.length) return responseType;
- responseType = value;
- return xhr;
- };
- xhr.response = function(value) {
- response = value;
- return xhr;
- };
- [ "get", "post" ].forEach(function(method) {
- xhr[method] = function() {
- return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
- };
- });
- xhr.send = function(method, data, callback) {
- if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
- request.open(method, url, true);
- if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
- if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
- if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
- if (responseType != null) request.responseType = responseType;
- if (callback != null) xhr.on("error", callback).on("load", function(request) {
- callback(null, request);
- });
- dispatch.beforesend.call(xhr, request);
- request.send(data == null ? null : data);
- return xhr;
- };
- xhr.abort = function() {
- request.abort();
- return xhr;
- };
- d3.rebind(xhr, dispatch, "on");
- return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
- }
- function d3_xhr_fixCallback(callback) {
- return callback.length === 1 ? function(error, request) {
- callback(error == null ? request : null);
- } : callback;
- }
- function d3_xhrHasResponse(request) {
- var type = request.responseType;
- return type && type !== "text" ? request.response : request.responseText;
- }
- d3.dsv = function(delimiter, mimeType) {
- var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
- function dsv(url, row, callback) {
- if (arguments.length < 3) callback = row, row = null;
- var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
- xhr.row = function(_) {
- return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
- };
- return xhr;
- }
- function response(request) {
- return dsv.parse(request.responseText);
- }
- function typedResponse(f) {
- return function(request) {
- return dsv.parse(request.responseText, f);
- };
- }
- dsv.parse = function(text, f) {
- var o;
- return dsv.parseRows(text, function(row, i) {
- if (o) return o(row, i - 1);
- var a = new Function("d", "return {" + row.map(function(name, i) {
- return JSON.stringify(name) + ": d[" + i + "]";
- }).join(",") + "}");
- o = f ? function(row, i) {
- return f(a(row), i);
- } : a;
- });
- };
- dsv.parseRows = function(text, f) {
- var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
- function token() {
- if (I >= N) return EOF;
- if (eol) return eol = false, EOL;
- var j = I;
- if (text.charCodeAt(j) === 34) {
- var i = j;
- while (i++ < N) {
- if (text.charCodeAt(i) === 34) {
- if (text.charCodeAt(i + 1) !== 34) break;
- ++i;
- }
- }
- I = i + 2;
- var c = text.charCodeAt(i + 1);
- if (c === 13) {
- eol = true;
- if (text.charCodeAt(i + 2) === 10) ++I;
- } else if (c === 10) {
- eol = true;
- }
- return text.slice(j + 1, i).replace(/""/g, '"');
- }
- while (I < N) {
- var c = text.charCodeAt(I++), k = 1;
- if (c === 10) eol = true; else if (c === 13) {
- eol = true;
- if (text.charCodeAt(I) === 10) ++I, ++k;
- } else if (c !== delimiterCode) continue;
- return text.slice(j, I - k);
- }
- return text.slice(j);
- }
- while ((t = token()) !== EOF) {
- var a = [];
- while (t !== EOL && t !== EOF) {
- a.push(t);
- t = token();
- }
- if (f && (a = f(a, n++)) == null) continue;
- rows.push(a);
- }
- return rows;
- };
- dsv.format = function(rows) {
- if (Array.isArray(rows[0])) return dsv.formatRows(rows);
- var fieldSet = new d3_Set(), fields = [];
- rows.forEach(function(row) {
- for (var field in row) {
- if (!fieldSet.has(field)) {
- fields.push(fieldSet.add(field));
- }
- }
- });
- return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
- return fields.map(function(field) {
- return formatValue(row[field]);
- }).join(delimiter);
- })).join("\n");
- };
- dsv.formatRows = function(rows) {
- return rows.map(formatRow).join("\n");
- };
- function formatRow(row) {
- return row.map(formatValue).join(delimiter);
- }
- function formatValue(text) {
- return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
- }
- return dsv;
- };
- d3.csv = d3.dsv(",", "text/csv");
- d3.tsv = d3.dsv(" ", "text/tab-separated-values");
- var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
- setTimeout(callback, 17);
- };
- d3.timer = function(callback, delay, then) {
- var n = arguments.length;
- if (n < 2) delay = 0;
- if (n < 3) then = Date.now();
- var time = then + delay, timer = {
- c: callback,
- t: time,
- f: false,
- n: null
- };
- if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
- d3_timer_queueTail = timer;
- if (!d3_timer_interval) {
- d3_timer_timeout = clearTimeout(d3_timer_timeout);
- d3_timer_interval = 1;
- d3_timer_frame(d3_timer_step);
- }
- };
- function d3_timer_step() {
- var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
- if (delay > 24) {
- if (isFinite(delay)) {
- clearTimeout(d3_timer_timeout);
- d3_timer_timeout = setTimeout(d3_timer_step, delay);
- }
- d3_timer_interval = 0;
- } else {
- d3_timer_interval = 1;
- d3_timer_frame(d3_timer_step);
- }
- }
- d3.timer.flush = function() {
- d3_timer_mark();
- d3_timer_sweep();
- };
- function d3_timer_mark() {
- var now = Date.now();
- d3_timer_active = d3_timer_queueHead;
- while (d3_timer_active) {
- if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
- d3_timer_active = d3_timer_active.n;
- }
- return now;
- }
- function d3_timer_sweep() {
- var t0, t1 = d3_timer_queueHead, time = Infinity;
- while (t1) {
- if (t1.f) {
- t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
- } else {
- if (t1.t < time) time = t1.t;
- t1 = (t0 = t1).n;
- }
- }
- d3_timer_queueTail = t0;
- return time;
- }
- function d3_format_precision(x, p) {
- return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
- }
- d3.round = function(x, n) {
- return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
- };
- var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
- d3.formatPrefix = function(value, precision) {
- var i = 0;
- if (value) {
- if (value < 0) value *= -1;
- if (precision) value = d3.round(value, d3_format_precision(value, precision));
- i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
- i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
- }
- return d3_formatPrefixes[8 + i / 3];
- };
- function d3_formatPrefix(d, i) {
- var k = Math.pow(10, abs(8 - i) * 3);
- return {
- scale: i > 8 ? function(d) {
- return d / k;
- } : function(d) {
- return d * k;
- },
- symbol: d
- };
- }
- function d3_locale_numberFormat(locale) {
- var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
- var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
- while (i > 0 && g > 0) {
- if (length + g + 1 > width) g = Math.max(1, width - length);
- t.push(value.substring(i -= g, i + g));
- if ((length += g + 1) > width) break;
- g = locale_grouping[j = (j + 1) % locale_grouping.length];
- }
- return t.reverse().join(locale_thousands);
- } : d3_identity;
- return function(specifier) {
- var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
- if (precision) precision = +precision.substring(1);
- if (zfill || fill === "0" && align === "=") {
- zfill = fill = "0";
- align = "=";
- }
- switch (type) {
- case "n":
- comma = true;
- type = "g";
- break;
-
- case "%":
- scale = 100;
- suffix = "%";
- type = "f";
- break;
-
- case "p":
- scale = 100;
- suffix = "%";
- type = "r";
- break;
-
- case "b":
- case "o":
- case "x":
- case "X":
- if (symbol === "#") prefix = "0" + type.toLowerCase();
-
- case "c":
- exponent = false;
-
- case "d":
- integer = true;
- precision = 0;
- break;
-
- case "s":
- scale = -1;
- type = "r";
- break;
- }
- if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
- if (type == "r" && !precision) type = "g";
- if (precision != null) {
- if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
- }
- type = d3_format_types.get(type) || d3_format_typeDefault;
- var zcomma = zfill && comma;
- return function(value) {
- var fullSuffix = suffix;
- if (integer && value % 1) return "";
- var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
- if (scale < 0) {
- var unit = d3.formatPrefix(value, precision);
- value = unit.scale(value);
- fullSuffix = unit.symbol + suffix;
- } else {
- value *= scale;
- }
- value = type(value, precision);
- var i = value.lastIndexOf("."), before, after;
- if (i < 0) {
- var j = exponent ? value.lastIndexOf("e") : -1;
- if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
- } else {
- before = value.substring(0, i);
- after = locale_decimal + value.substring(i + 1);
- }
- if (!zfill && comma) before = formatGroup(before, Infinity);
- var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
- if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
- negative += prefix;
- value = before + after;
- return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
- };
- };
- }
- var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
- var d3_format_types = d3.map({
- b: function(x) {
- return x.toString(2);
- },
- c: function(x) {
- return String.fromCharCode(x);
- },
- o: function(x) {
- return x.toString(8);
- },
- x: function(x) {
- return x.toString(16);
- },
- X: function(x) {
- return x.toString(16).toUpperCase();
- },
- g: function(x, p) {
- return x.toPrecision(p);
- },
- e: function(x, p) {
- return x.toExponential(p);
- },
- f: function(x, p) {
- return x.toFixed(p);
- },
- r: function(x, p) {
- return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
- }
- });
- function d3_format_typeDefault(x) {
- return x + "";
- }
- var d3_time = d3.time = {}, d3_date = Date;
- function d3_date_utc() {
- this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
- }
- d3_date_utc.prototype = {
- getDate: function() {
- return this._.getUTCDate();
- },
- getDay: function() {
- return this._.getUTCDay();
- },
- getFullYear: function() {
- return this._.getUTCFullYear();
- },
- getHours: function() {
- return this._.getUTCHours();
- },
- getMilliseconds: function() {
- return this._.getUTCMilliseconds();
- },
- getMinutes: function() {
- return this._.getUTCMinutes();
- },
- getMonth: function() {
- return this._.getUTCMonth();
- },
- getSeconds: function() {
- return this._.getUTCSeconds();
- },
- getTime: function() {
- return this._.getTime();
- },
- getTimezoneOffset: function() {
- return 0;
- },
- valueOf: function() {
- return this._.valueOf();
- },
- setDate: function() {
- d3_time_prototype.setUTCDate.apply(this._, arguments);
- },
- setDay: function() {
- d3_time_prototype.setUTCDay.apply(this._, arguments);
- },
- setFullYear: function() {
- d3_time_prototype.setUTCFullYear.apply(this._, arguments);
- },
- setHours: function() {
- d3_time_prototype.setUTCHours.apply(this._, arguments);
- },
- setMilliseconds: function() {
- d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
- },
- setMinutes: function() {
- d3_time_prototype.setUTCMinutes.apply(this._, arguments);
- },
- setMonth: function() {
- d3_time_prototype.setUTCMonth.apply(this._, arguments);
- },
- setSeconds: function() {
- d3_time_prototype.setUTCSeconds.apply(this._, arguments);
- },
- setTime: function() {
- d3_time_prototype.setTime.apply(this._, arguments);
- }
- };
- var d3_time_prototype = Date.prototype;
- function d3_time_interval(local, step, number) {
- function round(date) {
- var d0 = local(date), d1 = offset(d0, 1);
- return date - d0 < d1 - date ? d0 : d1;
- }
- function ceil(date) {
- step(date = local(new d3_date(date - 1)), 1);
- return date;
- }
- function offset(date, k) {
- step(date = new d3_date(+date), k);
- return date;
- }
- function range(t0, t1, dt) {
- var time = ceil(t0), times = [];
- if (dt > 1) {
- while (time < t1) {
- if (!(number(time) % dt)) times.push(new Date(+time));
- step(time, 1);
- }
- } else {
- while (time < t1) times.push(new Date(+time)), step(time, 1);
- }
- return times;
- }
- function range_utc(t0, t1, dt) {
- try {
- d3_date = d3_date_utc;
- var utc = new d3_date_utc();
- utc._ = t0;
- return range(utc, t1, dt);
- } finally {
- d3_date = Date;
- }
- }
- local.floor = local;
- local.round = round;
- local.ceil = ceil;
- local.offset = offset;
- local.range = range;
- var utc = local.utc = d3_time_interval_utc(local);
- utc.floor = utc;
- utc.round = d3_time_interval_utc(round);
- utc.ceil = d3_time_interval_utc(ceil);
- utc.offset = d3_time_interval_utc(offset);
- utc.range = range_utc;
- return local;
- }
- function d3_time_interval_utc(method) {
- return function(date, k) {
- try {
- d3_date = d3_date_utc;
- var utc = new d3_date_utc();
- utc._ = date;
- return method(utc, k)._;
- } finally {
- d3_date = Date;
- }
- };
- }
- d3_time.year = d3_time_interval(function(date) {
- date = d3_time.day(date);
- date.setMonth(0, 1);
- return date;
- }, function(date, offset) {
- date.setFullYear(date.getFullYear() + offset);
- }, function(date) {
- return date.getFullYear();
- });
- d3_time.years = d3_time.year.range;
- d3_time.years.utc = d3_time.year.utc.range;
- d3_time.day = d3_time_interval(function(date) {
- var day = new d3_date(2e3, 0);
- day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
- return day;
- }, function(date, offset) {
- date.setDate(date.getDate() + offset);
- }, function(date) {
- return date.getDate() - 1;
- });
- d3_time.days = d3_time.day.range;
- d3_time.days.utc = d3_time.day.utc.range;
- d3_time.dayOfYear = function(date) {
- var year = d3_time.year(date);
- return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
- };
- [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
- i = 7 - i;
- var interval = d3_time[day] = d3_time_interval(function(date) {
- (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
- return date;
- }, function(date, offset) {
- date.setDate(date.getDate() + Math.floor(offset) * 7);
- }, function(date) {
- var day = d3_time.year(date).getDay();
- return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
- });
- d3_time[day + "s"] = interval.range;
- d3_time[day + "s"].utc = interval.utc.range;
- d3_time[day + "OfYear"] = function(date) {
- var day = d3_time.year(date).getDay();
- return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
- };
- });
- d3_time.week = d3_time.sunday;
- d3_time.weeks = d3_time.sunday.range;
- d3_time.weeks.utc = d3_time.sunday.utc.range;
- d3_time.weekOfYear = d3_time.sundayOfYear;
- function d3_locale_timeFormat(locale) {
- var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
- function d3_time_format(template) {
- var n = template.length;
- function format(date) {
- var string = [], i = -1, j = 0, c, p, f;
- while (++i < n) {
- if (template.charCodeAt(i) === 37) {
- string.push(template.slice(j, i));
- if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
- if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
- string.push(c);
- j = i + 1;
- }
- }
- string.push(template.slice(j, i));
- return string.join("");
- }
- format.parse = function(string) {
- var d = {
- y: 1900,
- m: 0,
- d: 1,
- H: 0,
- M: 0,
- S: 0,
- L: 0,
- Z: null
- }, i = d3_time_parse(d, template, string, 0);
- if (i != string.length) return null;
- if ("p" in d) d.H = d.H % 12 + d.p * 12;
- var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
- if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
- date.setFullYear(d.y, 0, 1);
- dat
<TRUNCATED>
[14/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/backbone-1.1.2.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/backbone-1.1.2.js b/htrace-htraced/src/web/lib/js/backbone-1.1.2.js
deleted file mode 100644
index 5da4943..0000000
--- a/htrace-htraced/src/web/lib/js/backbone-1.1.2.js
+++ /dev/null
@@ -1,1608 +0,0 @@
-// Backbone.js 1.1.2
-
-// (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
-// Backbone may be freely distributed under the MIT license.
-// For all details and documentation:
-// http://backbonejs.org
-
-(function(root, factory) {
-
- // Set up Backbone appropriately for the environment. Start with AMD.
- if (typeof define === 'function' && define.amd) {
- define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
- // Export global even in AMD case in case this script is loaded with
- // others that may still expect a global Backbone.
- root.Backbone = factory(root, exports, _, $);
- });
-
- // Next for Node.js or CommonJS. jQuery may not be needed as a module.
- } else if (typeof exports !== 'undefined') {
- var _ = require('underscore');
- factory(root, exports, _);
-
- // Finally, as a browser global.
- } else {
- root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
- }
-
-}(this, function(root, Backbone, _, $) {
-
- // Initial Setup
- // -------------
-
- // Save the previous value of the `Backbone` variable, so that it can be
- // restored later on, if `noConflict` is used.
- var previousBackbone = root.Backbone;
-
- // Create local references to array methods we'll want to use later.
- var array = [];
- var push = array.push;
- var slice = array.slice;
- var splice = array.splice;
-
- // Current version of the library. Keep in sync with `package.json`.
- Backbone.VERSION = '1.1.2';
-
- // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
- // the `$` variable.
- Backbone.$ = $;
-
- // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
- // to its previous owner. Returns a reference to this Backbone object.
- Backbone.noConflict = function() {
- root.Backbone = previousBackbone;
- return this;
- };
-
- // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
- // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
- // set a `X-Http-Method-Override` header.
- Backbone.emulateHTTP = false;
-
- // Turn on `emulateJSON` to support legacy servers that can't deal with direct
- // `application/json` requests ... will encode the body as
- // `application/x-www-form-urlencoded` instead and will send the model in a
- // form param named `model`.
- Backbone.emulateJSON = false;
-
- // Backbone.Events
- // ---------------
-
- // A module that can be mixed in to *any object* in order to provide it with
- // custom events. You may bind with `on` or remove with `off` callback
- // functions to an event; `trigger`-ing an event fires all callbacks in
- // succession.
- //
- // var object = {};
- // _.extend(object, Backbone.Events);
- // object.on('expand', function(){ alert('expanded'); });
- // object.trigger('expand');
- //
- var Events = Backbone.Events = {
-
- // Bind an event to a `callback` function. Passing `"all"` will bind
- // the callback to all events fired.
- on: function(name, callback, context) {
- if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
- this._events || (this._events = {});
- var events = this._events[name] || (this._events[name] = []);
- events.push({callback: callback, context: context, ctx: context || this});
- return this;
- },
-
- // Bind an event to only be triggered a single time. After the first time
- // the callback is invoked, it will be removed.
- once: function(name, callback, context) {
- if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
- var self = this;
- var once = _.once(function() {
- self.off(name, once);
- callback.apply(this, arguments);
- });
- once._callback = callback;
- return this.on(name, once, context);
- },
-
- // Remove one or many callbacks. If `context` is null, removes all
- // callbacks with that function. If `callback` is null, removes all
- // callbacks for the event. If `name` is null, removes all bound
- // callbacks for all events.
- off: function(name, callback, context) {
- var retain, ev, events, names, i, l, j, k;
- if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
- if (!name && !callback && !context) {
- this._events = void 0;
- return this;
- }
- names = name ? [name] : _.keys(this._events);
- for (i = 0, l = names.length; i < l; i++) {
- name = names[i];
- if (events = this._events[name]) {
- this._events[name] = retain = [];
- if (callback || context) {
- for (j = 0, k = events.length; j < k; j++) {
- ev = events[j];
- if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
- (context && context !== ev.context)) {
- retain.push(ev);
- }
- }
- }
- if (!retain.length) delete this._events[name];
- }
- }
-
- return this;
- },
-
- // Trigger one or many events, firing all bound callbacks. Callbacks are
- // passed the same arguments as `trigger` is, apart from the event name
- // (unless you're listening on `"all"`, which will cause your callback to
- // receive the true name of the event as the first argument).
- trigger: function(name) {
- if (!this._events) return this;
- var args = slice.call(arguments, 1);
- if (!eventsApi(this, 'trigger', name, args)) return this;
- var events = this._events[name];
- var allEvents = this._events.all;
- if (events) triggerEvents(events, args);
- if (allEvents) triggerEvents(allEvents, arguments);
- return this;
- },
-
- // Tell this object to stop listening to either specific events ... or
- // to every object it's currently listening to.
- stopListening: function(obj, name, callback) {
- var listeningTo = this._listeningTo;
- if (!listeningTo) return this;
- var remove = !name && !callback;
- if (!callback && typeof name === 'object') callback = this;
- if (obj) (listeningTo = {})[obj._listenId] = obj;
- for (var id in listeningTo) {
- obj = listeningTo[id];
- obj.off(name, callback, this);
- if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
- }
- return this;
- }
-
- };
-
- // Regular expression used to split event strings.
- var eventSplitter = /\s+/;
-
- // Implement fancy features of the Events API such as multiple event
- // names `"change blur"` and jQuery-style event maps `{change: action}`
- // in terms of the existing API.
- var eventsApi = function(obj, action, name, rest) {
- if (!name) return true;
-
- // Handle event maps.
- if (typeof name === 'object') {
- for (var key in name) {
- obj[action].apply(obj, [key, name[key]].concat(rest));
- }
- return false;
- }
-
- // Handle space separated event names.
- if (eventSplitter.test(name)) {
- var names = name.split(eventSplitter);
- for (var i = 0, l = names.length; i < l; i++) {
- obj[action].apply(obj, [names[i]].concat(rest));
- }
- return false;
- }
-
- return true;
- };
-
- // A difficult-to-believe, but optimized internal dispatch function for
- // triggering events. Tries to keep the usual cases speedy (most internal
- // Backbone events have 3 arguments).
- var triggerEvents = function(events, args) {
- var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
- switch (args.length) {
- case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
- case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
- case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
- case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
- default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
- }
- };
-
- var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
-
- // Inversion-of-control versions of `on` and `once`. Tell *this* object to
- // listen to an event in another object ... keeping track of what it's
- // listening to.
- _.each(listenMethods, function(implementation, method) {
- Events[method] = function(obj, name, callback) {
- var listeningTo = this._listeningTo || (this._listeningTo = {});
- var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
- listeningTo[id] = obj;
- if (!callback && typeof name === 'object') callback = this;
- obj[implementation](name, callback, this);
- return this;
- };
- });
-
- // Aliases for backwards compatibility.
- Events.bind = Events.on;
- Events.unbind = Events.off;
-
- // Allow the `Backbone` object to serve as a global event bus, for folks who
- // want global "pubsub" in a convenient place.
- _.extend(Backbone, Events);
-
- // Backbone.Model
- // --------------
-
- // Backbone **Models** are the basic data object in the framework --
- // frequently representing a row in a table in a database on your server.
- // A discrete chunk of data and a bunch of useful, related methods for
- // performing computations and transformations on that data.
-
- // Create a new model with the specified attributes. A client id (`cid`)
- // is automatically generated and assigned for you.
- var Model = Backbone.Model = function(attributes, options) {
- var attrs = attributes || {};
- options || (options = {});
- this.cid = _.uniqueId('c');
- this.attributes = {};
- if (options.collection) this.collection = options.collection;
- if (options.parse) attrs = this.parse(attrs, options) || {};
- attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
- this.set(attrs, options);
- this.changed = {};
- this.initialize.apply(this, arguments);
- };
-
- // Attach all inheritable methods to the Model prototype.
- _.extend(Model.prototype, Events, {
-
- // A hash of attributes whose current and previous value differ.
- changed: null,
-
- // The value returned during the last failed validation.
- validationError: null,
-
- // The default name for the JSON `id` attribute is `"id"`. MongoDB and
- // CouchDB users may want to set this to `"_id"`.
- idAttribute: 'id',
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // Return a copy of the model's `attributes` object.
- toJSON: function(options) {
- return _.clone(this.attributes);
- },
-
- // Proxy `Backbone.sync` by default -- but override this if you need
- // custom syncing semantics for *this* particular model.
- sync: function() {
- return Backbone.sync.apply(this, arguments);
- },
-
- // Get the value of an attribute.
- get: function(attr) {
- return this.attributes[attr];
- },
-
- // Get the HTML-escaped value of an attribute.
- escape: function(attr) {
- return _.escape(this.get(attr));
- },
-
- // Returns `true` if the attribute contains a value that is not null
- // or undefined.
- has: function(attr) {
- return this.get(attr) != null;
- },
-
- // Set a hash of model attributes on the object, firing `"change"`. This is
- // the core primitive operation of a model, updating the data and notifying
- // anyone who needs to know about the change in state. The heart of the beast.
- set: function(key, val, options) {
- var attr, attrs, unset, changes, silent, changing, prev, current;
- if (key == null) return this;
-
- // Handle both `"key", value` and `{key: value}` -style arguments.
- if (typeof key === 'object') {
- attrs = key;
- options = val;
- } else {
- (attrs = {})[key] = val;
- }
-
- options || (options = {});
-
- // Run validation.
- if (!this._validate(attrs, options)) return false;
-
- // Extract attributes and options.
- unset = options.unset;
- silent = options.silent;
- changes = [];
- changing = this._changing;
- this._changing = true;
-
- if (!changing) {
- this._previousAttributes = _.clone(this.attributes);
- this.changed = {};
- }
- current = this.attributes, prev = this._previousAttributes;
-
- // Check for changes of `id`.
- if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
-
- // For each `set` attribute, update or delete the current value.
- for (attr in attrs) {
- val = attrs[attr];
- if (!_.isEqual(current[attr], val)) changes.push(attr);
- if (!_.isEqual(prev[attr], val)) {
- this.changed[attr] = val;
- } else {
- delete this.changed[attr];
- }
- unset ? delete current[attr] : current[attr] = val;
- }
-
- // Trigger all relevant attribute changes.
- if (!silent) {
- if (changes.length) this._pending = options;
- for (var i = 0, l = changes.length; i < l; i++) {
- this.trigger('change:' + changes[i], this, current[changes[i]], options);
- }
- }
-
- // You might be wondering why there's a `while` loop here. Changes can
- // be recursively nested within `"change"` events.
- if (changing) return this;
- if (!silent) {
- while (this._pending) {
- options = this._pending;
- this._pending = false;
- this.trigger('change', this, options);
- }
- }
- this._pending = false;
- this._changing = false;
- return this;
- },
-
- // Remove an attribute from the model, firing `"change"`. `unset` is a noop
- // if the attribute doesn't exist.
- unset: function(attr, options) {
- return this.set(attr, void 0, _.extend({}, options, {unset: true}));
- },
-
- // Clear all attributes on the model, firing `"change"`.
- clear: function(options) {
- var attrs = {};
- for (var key in this.attributes) attrs[key] = void 0;
- return this.set(attrs, _.extend({}, options, {unset: true}));
- },
-
- // Determine if the model has changed since the last `"change"` event.
- // If you specify an attribute name, determine if that attribute has changed.
- hasChanged: function(attr) {
- if (attr == null) return !_.isEmpty(this.changed);
- return _.has(this.changed, attr);
- },
-
- // Return an object containing all the attributes that have changed, or
- // false if there are no changed attributes. Useful for determining what
- // parts of a view need to be updated and/or what attributes need to be
- // persisted to the server. Unset attributes will be set to undefined.
- // You can also pass an attributes object to diff against the model,
- // determining if there *would be* a change.
- changedAttributes: function(diff) {
- if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
- var val, changed = false;
- var old = this._changing ? this._previousAttributes : this.attributes;
- for (var attr in diff) {
- if (_.isEqual(old[attr], (val = diff[attr]))) continue;
- (changed || (changed = {}))[attr] = val;
- }
- return changed;
- },
-
- // Get the previous value of an attribute, recorded at the time the last
- // `"change"` event was fired.
- previous: function(attr) {
- if (attr == null || !this._previousAttributes) return null;
- return this._previousAttributes[attr];
- },
-
- // Get all of the attributes of the model at the time of the previous
- // `"change"` event.
- previousAttributes: function() {
- return _.clone(this._previousAttributes);
- },
-
- // Fetch the model from the server. If the server's representation of the
- // model differs from its current attributes, they will be overridden,
- // triggering a `"change"` event.
- fetch: function(options) {
- options = options ? _.clone(options) : {};
- if (options.parse === void 0) options.parse = true;
- var model = this;
- var success = options.success;
- options.success = function(resp) {
- if (!model.set(model.parse(resp, options), options)) return false;
- if (success) success(model, resp, options);
- model.trigger('sync', model, resp, options);
- };
- wrapError(this, options);
- return this.sync('read', this, options);
- },
-
- // Set a hash of model attributes, and sync the model to the server.
- // If the server returns an attributes hash that differs, the model's
- // state will be `set` again.
- save: function(key, val, options) {
- var attrs, method, xhr, attributes = this.attributes;
-
- // Handle both `"key", value` and `{key: value}` -style arguments.
- if (key == null || typeof key === 'object') {
- attrs = key;
- options = val;
- } else {
- (attrs = {})[key] = val;
- }
-
- options = _.extend({validate: true}, options);
-
- // If we're not waiting and attributes exist, save acts as
- // `set(attr).save(null, opts)` with validation. Otherwise, check if
- // the model will be valid when the attributes, if any, are set.
- if (attrs && !options.wait) {
- if (!this.set(attrs, options)) return false;
- } else {
- if (!this._validate(attrs, options)) return false;
- }
-
- // Set temporary attributes if `{wait: true}`.
- if (attrs && options.wait) {
- this.attributes = _.extend({}, attributes, attrs);
- }
-
- // After a successful server-side save, the client is (optionally)
- // updated with the server-side state.
- if (options.parse === void 0) options.parse = true;
- var model = this;
- var success = options.success;
- options.success = function(resp) {
- // Ensure attributes are restored during synchronous saves.
- model.attributes = attributes;
- var serverAttrs = model.parse(resp, options);
- if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
- if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
- return false;
- }
- if (success) success(model, resp, options);
- model.trigger('sync', model, resp, options);
- };
- wrapError(this, options);
-
- method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
- if (method === 'patch') options.attrs = attrs;
- xhr = this.sync(method, this, options);
-
- // Restore attributes.
- if (attrs && options.wait) this.attributes = attributes;
-
- return xhr;
- },
-
- // Destroy this model on the server if it was already persisted.
- // Optimistically removes the model from its collection, if it has one.
- // If `wait: true` is passed, waits for the server to respond before removal.
- destroy: function(options) {
- options = options ? _.clone(options) : {};
- var model = this;
- var success = options.success;
-
- var destroy = function() {
- model.trigger('destroy', model, model.collection, options);
- };
-
- options.success = function(resp) {
- if (options.wait || model.isNew()) destroy();
- if (success) success(model, resp, options);
- if (!model.isNew()) model.trigger('sync', model, resp, options);
- };
-
- if (this.isNew()) {
- options.success();
- return false;
- }
- wrapError(this, options);
-
- var xhr = this.sync('delete', this, options);
- if (!options.wait) destroy();
- return xhr;
- },
-
- // Default URL for the model's representation on the server -- if you're
- // using Backbone's restful methods, override this to change the endpoint
- // that will be called.
- url: function() {
- var base =
- _.result(this, 'urlRoot') ||
- _.result(this.collection, 'url') ||
- urlError();
- if (this.isNew()) return base;
- return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
- },
-
- // **parse** converts a response into the hash of attributes to be `set` on
- // the model. The default implementation is just to pass the response along.
- parse: function(resp, options) {
- return resp;
- },
-
- // Create a new model with identical attributes to this one.
- clone: function() {
- return new this.constructor(this.attributes);
- },
-
- // A model is new if it has never been saved to the server, and lacks an id.
- isNew: function() {
- return !this.has(this.idAttribute);
- },
-
- // Check if the model is currently in a valid state.
- isValid: function(options) {
- return this._validate({}, _.extend(options || {}, { validate: true }));
- },
-
- // Run validation against the next complete set of model attributes,
- // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
- _validate: function(attrs, options) {
- if (!options.validate || !this.validate) return true;
- attrs = _.extend({}, this.attributes, attrs);
- var error = this.validationError = this.validate(attrs, options) || null;
- if (!error) return true;
- this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
- return false;
- }
-
- });
-
- // Underscore methods that we want to implement on the Model.
- var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit'];
-
- // Mix in each Underscore method as a proxy to `Model#attributes`.
- _.each(modelMethods, function(method) {
- Model.prototype[method] = function() {
- var args = slice.call(arguments);
- args.unshift(this.attributes);
- return _[method].apply(_, args);
- };
- });
-
- // Backbone.Collection
- // -------------------
-
- // If models tend to represent a single row of data, a Backbone Collection is
- // more analagous to a table full of data ... or a small slice or page of that
- // table, or a collection of rows that belong together for a particular reason
- // -- all of the messages in this particular folder, all of the documents
- // belonging to this particular author, and so on. Collections maintain
- // indexes of their models, both in order, and for lookup by `id`.
-
- // Create a new **Collection**, perhaps to contain a specific type of `model`.
- // If a `comparator` is specified, the Collection will maintain
- // its models in sort order, as they're added and removed.
- var Collection = Backbone.Collection = function(models, options) {
- options || (options = {});
- if (options.model) this.model = options.model;
- if (options.comparator !== void 0) this.comparator = options.comparator;
- this._reset();
- this.initialize.apply(this, arguments);
- if (models) this.reset(models, _.extend({silent: true}, options));
- };
-
- // Default options for `Collection#set`.
- var setOptions = {add: true, remove: true, merge: true};
- var addOptions = {add: true, remove: false};
-
- // Define the Collection's inheritable methods.
- _.extend(Collection.prototype, Events, {
-
- // The default model for a collection is just a **Backbone.Model**.
- // This should be overridden in most cases.
- model: Model,
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // The JSON representation of a Collection is an array of the
- // models' attributes.
- toJSON: function(options) {
- return this.map(function(model){ return model.toJSON(options); });
- },
-
- // Proxy `Backbone.sync` by default.
- sync: function() {
- return Backbone.sync.apply(this, arguments);
- },
-
- // Add a model, or list of models to the set.
- add: function(models, options) {
- return this.set(models, _.extend({merge: false}, options, addOptions));
- },
-
- // Remove a model, or a list of models from the set.
- remove: function(models, options) {
- var singular = !_.isArray(models);
- models = singular ? [models] : _.clone(models);
- options || (options = {});
- var i, l, index, model;
- for (i = 0, l = models.length; i < l; i++) {
- model = models[i] = this.get(models[i]);
- if (!model) continue;
- delete this._byId[model.id];
- delete this._byId[model.cid];
- index = this.indexOf(model);
- this.models.splice(index, 1);
- this.length--;
- if (!options.silent) {
- options.index = index;
- model.trigger('remove', model, this, options);
- }
- this._removeReference(model, options);
- }
- return singular ? models[0] : models;
- },
-
- // Update a collection by `set`-ing a new list of models, adding new ones,
- // removing models that are no longer present, and merging models that
- // already exist in the collection, as necessary. Similar to **Model#set**,
- // the core operation for updating the data contained by the collection.
- set: function(models, options) {
- options = _.defaults({}, options, setOptions);
- if (options.parse) models = this.parse(models, options);
- var singular = !_.isArray(models);
- models = singular ? (models ? [models] : []) : _.clone(models);
- var i, l, id, model, attrs, existing, sort;
- var at = options.at;
- var targetModel = this.model;
- var sortable = this.comparator && (at == null) && options.sort !== false;
- var sortAttr = _.isString(this.comparator) ? this.comparator : null;
- var toAdd = [], toRemove = [], modelMap = {};
- var add = options.add, merge = options.merge, remove = options.remove;
- var order = !sortable && add && remove ? [] : false;
-
- // Turn bare objects into model references, and prevent invalid models
- // from being added.
- for (i = 0, l = models.length; i < l; i++) {
- attrs = models[i] || {};
- if (attrs instanceof Model) {
- id = model = attrs;
- } else {
- id = attrs[targetModel.prototype.idAttribute || 'id'];
- }
-
- // If a duplicate is found, prevent it from being added and
- // optionally merge it into the existing model.
- if (existing = this.get(id)) {
- if (remove) modelMap[existing.cid] = true;
- if (merge) {
- attrs = attrs === model ? model.attributes : attrs;
- if (options.parse) attrs = existing.parse(attrs, options);
- existing.set(attrs, options);
- if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
- }
- models[i] = existing;
-
- // If this is a new, valid model, push it to the `toAdd` list.
- } else if (add) {
- model = models[i] = this._prepareModel(attrs, options);
- if (!model) continue;
- toAdd.push(model);
- this._addReference(model, options);
- }
-
- // Do not add multiple models with the same `id`.
- model = existing || model;
- if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
- modelMap[model.id] = true;
- }
-
- // Remove nonexistent models if appropriate.
- if (remove) {
- for (i = 0, l = this.length; i < l; ++i) {
- if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
- }
- if (toRemove.length) this.remove(toRemove, options);
- }
-
- // See if sorting is needed, update `length` and splice in new models.
- if (toAdd.length || (order && order.length)) {
- if (sortable) sort = true;
- this.length += toAdd.length;
- if (at != null) {
- for (i = 0, l = toAdd.length; i < l; i++) {
- this.models.splice(at + i, 0, toAdd[i]);
- }
- } else {
- if (order) this.models.length = 0;
- var orderedModels = order || toAdd;
- for (i = 0, l = orderedModels.length; i < l; i++) {
- this.models.push(orderedModels[i]);
- }
- }
- }
-
- // Silently sort the collection if appropriate.
- if (sort) this.sort({silent: true});
-
- // Unless silenced, it's time to fire all appropriate add/sort events.
- if (!options.silent) {
- for (i = 0, l = toAdd.length; i < l; i++) {
- (model = toAdd[i]).trigger('add', model, this, options);
- }
- if (sort || (order && order.length)) this.trigger('sort', this, options);
- }
-
- // Return the added (or merged) model (or models).
- return singular ? models[0] : models;
- },
-
- // When you have more items than you want to add or remove individually,
- // you can reset the entire set with a new list of models, without firing
- // any granular `add` or `remove` events. Fires `reset` when finished.
- // Useful for bulk operations and optimizations.
- reset: function(models, options) {
- options || (options = {});
- for (var i = 0, l = this.models.length; i < l; i++) {
- this._removeReference(this.models[i], options);
- }
- options.previousModels = this.models;
- this._reset();
- models = this.add(models, _.extend({silent: true}, options));
- if (!options.silent) this.trigger('reset', this, options);
- return models;
- },
-
- // Add a model to the end of the collection.
- push: function(model, options) {
- return this.add(model, _.extend({at: this.length}, options));
- },
-
- // Remove a model from the end of the collection.
- pop: function(options) {
- var model = this.at(this.length - 1);
- this.remove(model, options);
- return model;
- },
-
- // Add a model to the beginning of the collection.
- unshift: function(model, options) {
- return this.add(model, _.extend({at: 0}, options));
- },
-
- // Remove a model from the beginning of the collection.
- shift: function(options) {
- var model = this.at(0);
- this.remove(model, options);
- return model;
- },
-
- // Slice out a sub-array of models from the collection.
- slice: function() {
- return slice.apply(this.models, arguments);
- },
-
- // Get a model from the set by id.
- get: function(obj) {
- if (obj == null) return void 0;
- return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
- },
-
- // Get the model at the given index.
- at: function(index) {
- return this.models[index];
- },
-
- // Return models with matching attributes. Useful for simple cases of
- // `filter`.
- where: function(attrs, first) {
- if (_.isEmpty(attrs)) return first ? void 0 : [];
- return this[first ? 'find' : 'filter'](function(model) {
- for (var key in attrs) {
- if (attrs[key] !== model.get(key)) return false;
- }
- return true;
- });
- },
-
- // Return the first model with matching attributes. Useful for simple cases
- // of `find`.
- findWhere: function(attrs) {
- return this.where(attrs, true);
- },
-
- // Force the collection to re-sort itself. You don't need to call this under
- // normal circumstances, as the set will maintain sort order as each item
- // is added.
- sort: function(options) {
- if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
- options || (options = {});
-
- // Run sort based on type of `comparator`.
- if (_.isString(this.comparator) || this.comparator.length === 1) {
- this.models = this.sortBy(this.comparator, this);
- } else {
- this.models.sort(_.bind(this.comparator, this));
- }
-
- if (!options.silent) this.trigger('sort', this, options);
- return this;
- },
-
- // Pluck an attribute from each model in the collection.
- pluck: function(attr) {
- return _.invoke(this.models, 'get', attr);
- },
-
- // Fetch the default set of models for this collection, resetting the
- // collection when they arrive. If `reset: true` is passed, the response
- // data will be passed through the `reset` method instead of `set`.
- fetch: function(options) {
- options = options ? _.clone(options) : {};
- if (options.parse === void 0) options.parse = true;
- var success = options.success;
- var collection = this;
- options.success = function(resp) {
- var method = options.reset ? 'reset' : 'set';
- collection[method](resp, options);
- if (success) success(collection, resp, options);
- collection.trigger('sync', collection, resp, options);
- };
- wrapError(this, options);
- return this.sync('read', this, options);
- },
-
- // Create a new instance of a model in this collection. Add the model to the
- // collection immediately, unless `wait: true` is passed, in which case we
- // wait for the server to agree.
- create: function(model, options) {
- options = options ? _.clone(options) : {};
- if (!(model = this._prepareModel(model, options))) return false;
- if (!options.wait) this.add(model, options);
- var collection = this;
- var success = options.success;
- options.success = function(model, resp) {
- if (options.wait) collection.add(model, options);
- if (success) success(model, resp, options);
- };
- model.save(null, options);
- return model;
- },
-
- // **parse** converts a response into a list of models to be added to the
- // collection. The default implementation is just to pass it through.
- parse: function(resp, options) {
- return resp;
- },
-
- // Create a new collection with an identical list of models as this one.
- clone: function() {
- return new this.constructor(this.models);
- },
-
- // Private method to reset all internal state. Called when the collection
- // is first initialized or reset.
- _reset: function() {
- this.length = 0;
- this.models = [];
- this._byId = {};
- },
-
- // Prepare a hash of attributes (or other model) to be added to this
- // collection.
- _prepareModel: function(attrs, options) {
- if (attrs instanceof Model) return attrs;
- options = options ? _.clone(options) : {};
- options.collection = this;
- var model = new this.model(attrs, options);
- if (!model.validationError) return model;
- this.trigger('invalid', this, model.validationError, options);
- return false;
- },
-
- // Internal method to create a model's ties to a collection.
- _addReference: function(model, options) {
- this._byId[model.cid] = model;
- if (model.id != null) this._byId[model.id] = model;
- if (!model.collection) model.collection = this;
- model.on('all', this._onModelEvent, this);
- },
-
- // Internal method to sever a model's ties to a collection.
- _removeReference: function(model, options) {
- if (this === model.collection) delete model.collection;
- model.off('all', this._onModelEvent, this);
- },
-
- // Internal method called every time a model in the set fires an event.
- // Sets need to update their indexes when models change ids. All other
- // events simply proxy through. "add" and "remove" events that originate
- // in other collections are ignored.
- _onModelEvent: function(event, model, collection, options) {
- if ((event === 'add' || event === 'remove') && collection !== this) return;
- if (event === 'destroy') this.remove(model, options);
- if (model && event === 'change:' + model.idAttribute) {
- delete this._byId[model.previous(model.idAttribute)];
- if (model.id != null) this._byId[model.id] = model;
- }
- this.trigger.apply(this, arguments);
- }
-
- });
-
- // Underscore methods that we want to implement on the Collection.
- // 90% of the core usefulness of Backbone Collections is actually implemented
- // right here:
- var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
- 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
- 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
- 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
- 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
- 'lastIndexOf', 'isEmpty', 'chain', 'sample'];
-
- // Mix in each Underscore method as a proxy to `Collection#models`.
- _.each(methods, function(method) {
- Collection.prototype[method] = function() {
- var args = slice.call(arguments);
- args.unshift(this.models);
- return _[method].apply(_, args);
- };
- });
-
- // Underscore methods that take a property name as an argument.
- var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
-
- // Use attributes instead of properties.
- _.each(attributeMethods, function(method) {
- Collection.prototype[method] = function(value, context) {
- var iterator = _.isFunction(value) ? value : function(model) {
- return model.get(value);
- };
- return _[method](this.models, iterator, context);
- };
- });
-
- // Backbone.View
- // -------------
-
- // Backbone Views are almost more convention than they are actual code. A View
- // is simply a JavaScript object that represents a logical chunk of UI in the
- // DOM. This might be a single item, an entire list, a sidebar or panel, or
- // even the surrounding frame which wraps your whole app. Defining a chunk of
- // UI as a **View** allows you to define your DOM events declaratively, without
- // having to worry about render order ... and makes it easy for the view to
- // react to specific changes in the state of your models.
-
- // Creating a Backbone.View creates its initial element outside of the DOM,
- // if an existing element is not provided...
- var View = Backbone.View = function(options) {
- this.cid = _.uniqueId('view');
- options || (options = {});
- _.extend(this, _.pick(options, viewOptions));
- this._ensureElement();
- this.initialize.apply(this, arguments);
- this.delegateEvents();
- };
-
- // Cached regex to split keys for `delegate`.
- var delegateEventSplitter = /^(\S+)\s*(.*)$/;
-
- // List of view options to be merged as properties.
- var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
-
- // Set up all inheritable **Backbone.View** properties and methods.
- _.extend(View.prototype, Events, {
-
- // The default `tagName` of a View's element is `"div"`.
- tagName: 'div',
-
- // jQuery delegate for element lookup, scoped to DOM elements within the
- // current view. This should be preferred to global lookups where possible.
- $: function(selector) {
- return this.$el.find(selector);
- },
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // **render** is the core function that your view should override, in order
- // to populate its element (`this.el`), with the appropriate HTML. The
- // convention is for **render** to always return `this`.
- render: function() {
- return this;
- },
-
- // Remove this view by taking the element out of the DOM, and removing any
- // applicable Backbone.Events listeners.
- remove: function() {
- this.$el.remove();
- this.stopListening();
- return this;
- },
-
- // Change the view's element (`this.el` property), including event
- // re-delegation.
- setElement: function(element, delegate) {
- if (this.$el) this.undelegateEvents();
- this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
- this.el = this.$el[0];
- if (delegate !== false) this.delegateEvents();
- return this;
- },
-
- // Set callbacks, where `this.events` is a hash of
- //
- // *{"event selector": "callback"}*
- //
- // {
- // 'mousedown .title': 'edit',
- // 'click .button': 'save',
- // 'click .open': function(e) { ... }
- // }
- //
- // pairs. Callbacks will be bound to the view, with `this` set properly.
- // Uses event delegation for efficiency.
- // Omitting the selector binds the event to `this.el`.
- // This only works for delegate-able events: not `focus`, `blur`, and
- // not `change`, `submit`, and `reset` in Internet Explorer.
- delegateEvents: function(events) {
- if (!(events || (events = _.result(this, 'events')))) return this;
- this.undelegateEvents();
- for (var key in events) {
- var method = events[key];
- if (!_.isFunction(method)) method = this[events[key]];
- if (!method) continue;
-
- var match = key.match(delegateEventSplitter);
- var eventName = match[1], selector = match[2];
- method = _.bind(method, this);
- eventName += '.delegateEvents' + this.cid;
- if (selector === '') {
- this.$el.on(eventName, method);
- } else {
- this.$el.on(eventName, selector, method);
- }
- }
- return this;
- },
-
- // Clears all callbacks previously bound to the view with `delegateEvents`.
- // You usually don't need to use this, but may wish to if you have multiple
- // Backbone views attached to the same DOM element.
- undelegateEvents: function() {
- this.$el.off('.delegateEvents' + this.cid);
- return this;
- },
-
- // Ensure that the View has a DOM element to render into.
- // If `this.el` is a string, pass it through `$()`, take the first
- // matching element, and re-assign it to `el`. Otherwise, create
- // an element from the `id`, `className` and `tagName` properties.
- _ensureElement: function() {
- if (!this.el) {
- var attrs = _.extend({}, _.result(this, 'attributes'));
- if (this.id) attrs.id = _.result(this, 'id');
- if (this.className) attrs['class'] = _.result(this, 'className');
- var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);
- this.setElement($el, false);
- } else {
- this.setElement(_.result(this, 'el'), false);
- }
- }
-
- });
-
- // Backbone.sync
- // -------------
-
- // Override this function to change the manner in which Backbone persists
- // models to the server. You will be passed the type of request, and the
- // model in question. By default, makes a RESTful Ajax request
- // to the model's `url()`. Some possible customizations could be:
- //
- // * Use `setTimeout` to batch rapid-fire updates into a single request.
- // * Send up the models as XML instead of JSON.
- // * Persist models via WebSockets instead of Ajax.
- //
- // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
- // as `POST`, with a `_method` parameter containing the true HTTP method,
- // as well as all requests with the body as `application/x-www-form-urlencoded`
- // instead of `application/json` with the model in a param named `model`.
- // Useful when interfacing with server-side languages like **PHP** that make
- // it difficult to read the body of `PUT` requests.
- Backbone.sync = function(method, model, options) {
- var type = methodMap[method];
-
- // Default options, unless specified.
- _.defaults(options || (options = {}), {
- emulateHTTP: Backbone.emulateHTTP,
- emulateJSON: Backbone.emulateJSON
- });
-
- // Default JSON-request options.
- var params = {type: type, dataType: 'json'};
-
- // Ensure that we have a URL.
- if (!options.url) {
- params.url = _.result(model, 'url') || urlError();
- }
-
- // Ensure that we have the appropriate request data.
- if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
- params.contentType = 'application/json';
- params.data = JSON.stringify(options.attrs || model.toJSON(options));
- }
-
- // For older servers, emulate JSON by encoding the request into an HTML-form.
- if (options.emulateJSON) {
- params.contentType = 'application/x-www-form-urlencoded';
- params.data = params.data ? {model: params.data} : {};
- }
-
- // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
- // And an `X-HTTP-Method-Override` header.
- if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
- params.type = 'POST';
- if (options.emulateJSON) params.data._method = type;
- var beforeSend = options.beforeSend;
- options.beforeSend = function(xhr) {
- xhr.setRequestHeader('X-HTTP-Method-Override', type);
- if (beforeSend) return beforeSend.apply(this, arguments);
- };
- }
-
- // Don't process data on a non-GET request.
- if (params.type !== 'GET' && !options.emulateJSON) {
- params.processData = false;
- }
-
- // If we're sending a `PATCH` request, and we're in an old Internet Explorer
- // that still has ActiveX enabled by default, override jQuery to use that
- // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
- if (params.type === 'PATCH' && noXhrPatch) {
- params.xhr = function() {
- return new ActiveXObject("Microsoft.XMLHTTP");
- };
- }
-
- // Make the request, allowing the user to override any Ajax options.
- var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
- model.trigger('request', model, xhr, options);
- return xhr;
- };
-
- var noXhrPatch =
- typeof window !== 'undefined' && !!window.ActiveXObject &&
- !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
-
- // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
- var methodMap = {
- 'create': 'POST',
- 'update': 'PUT',
- 'patch': 'PATCH',
- 'delete': 'DELETE',
- 'read': 'GET'
- };
-
- // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
- // Override this if you'd like to use a different library.
- Backbone.ajax = function() {
- return Backbone.$.ajax.apply(Backbone.$, arguments);
- };
-
- // Backbone.Router
- // ---------------
-
- // Routers map faux-URLs to actions, and fire events when routes are
- // matched. Creating a new one sets its `routes` hash, if not set statically.
- var Router = Backbone.Router = function(options) {
- options || (options = {});
- if (options.routes) this.routes = options.routes;
- this._bindRoutes();
- this.initialize.apply(this, arguments);
- };
-
- // Cached regular expressions for matching named param parts and splatted
- // parts of route strings.
- var optionalParam = /\((.*?)\)/g;
- var namedParam = /(\(\?)?:\w+/g;
- var splatParam = /\*\w+/g;
- var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
-
- // Set up all inheritable **Backbone.Router** properties and methods.
- _.extend(Router.prototype, Events, {
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // Manually bind a single named route to a callback. For example:
- //
- // this.route('search/:query/p:num', 'search', function(query, num) {
- // ...
- // });
- //
- route: function(route, name, callback) {
- if (!_.isRegExp(route)) route = this._routeToRegExp(route);
- if (_.isFunction(name)) {
- callback = name;
- name = '';
- }
- if (!callback) callback = this[name];
- var router = this;
- Backbone.history.route(route, function(fragment) {
- var args = router._extractParameters(route, fragment);
- router.execute(callback, args);
- router.trigger.apply(router, ['route:' + name].concat(args));
- router.trigger('route', name, args);
- Backbone.history.trigger('route', router, name, args);
- });
- return this;
- },
-
- // Execute a route handler with the provided parameters. This is an
- // excellent place to do pre-route setup or post-route cleanup.
- execute: function(callback, args) {
- if (callback) callback.apply(this, args);
- },
-
- // Simple proxy to `Backbone.history` to save a fragment into the history.
- navigate: function(fragment, options) {
- Backbone.history.navigate(fragment, options);
- return this;
- },
-
- // Bind all defined routes to `Backbone.history`. We have to reverse the
- // order of the routes here to support behavior where the most general
- // routes can be defined at the bottom of the route map.
- _bindRoutes: function() {
- if (!this.routes) return;
- this.routes = _.result(this, 'routes');
- var route, routes = _.keys(this.routes);
- while ((route = routes.pop()) != null) {
- this.route(route, this.routes[route]);
- }
- },
-
- // Convert a route string into a regular expression, suitable for matching
- // against the current location hash.
- _routeToRegExp: function(route) {
- route = route.replace(escapeRegExp, '\\$&')
- .replace(optionalParam, '(?:$1)?')
- .replace(namedParam, function(match, optional) {
- return optional ? match : '([^/?]+)';
- })
- .replace(splatParam, '([^?]*?)');
- return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
- },
-
- // Given a route, and a URL fragment that it matches, return the array of
- // extracted decoded parameters. Empty or unmatched parameters will be
- // treated as `null` to normalize cross-browser behavior.
- _extractParameters: function(route, fragment) {
- var params = route.exec(fragment).slice(1);
- return _.map(params, function(param, i) {
- // Don't decode the search params.
- if (i === params.length - 1) return param || null;
- return param ? decodeURIComponent(param) : null;
- });
- }
-
- });
-
- // Backbone.History
- // ----------------
-
- // Handles cross-browser history management, based on either
- // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
- // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
- // and URL fragments. If the browser supports neither (old IE, natch),
- // falls back to polling.
- var History = Backbone.History = function() {
- this.handlers = [];
- _.bindAll(this, 'checkUrl');
-
- // Ensure that `History` can be used outside of the browser.
- if (typeof window !== 'undefined') {
- this.location = window.location;
- this.history = window.history;
- }
- };
-
- // Cached regex for stripping a leading hash/slash and trailing space.
- var routeStripper = /^[#\/]|\s+$/g;
-
- // Cached regex for stripping leading and trailing slashes.
- var rootStripper = /^\/+|\/+$/g;
-
- // Cached regex for detecting MSIE.
- var isExplorer = /msie [\w.]+/;
-
- // Cached regex for removing a trailing slash.
- var trailingSlash = /\/$/;
-
- // Cached regex for stripping urls of hash.
- var pathStripper = /#.*$/;
-
- // Has the history handling already been started?
- History.started = false;
-
- // Set up all inheritable **Backbone.History** properties and methods.
- _.extend(History.prototype, Events, {
-
- // The default interval to poll for hash changes, if necessary, is
- // twenty times a second.
- interval: 50,
-
- // Are we at the app root?
- atRoot: function() {
- return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root;
- },
-
- // Gets the true hash value. Cannot use location.hash directly due to bug
- // in Firefox where location.hash will always be decoded.
- getHash: function(window) {
- var match = (window || this).location.href.match(/#(.*)$/);
- return match ? match[1] : '';
- },
-
- // Get the cross-browser normalized URL fragment, either from the URL,
- // the hash, or the override.
- getFragment: function(fragment, forcePushState) {
- if (fragment == null) {
- if (this._hasPushState || !this._wantsHashChange || forcePushState) {
- fragment = decodeURI(this.location.pathname + this.location.search);
- var root = this.root.replace(trailingSlash, '');
- if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
- } else {
- fragment = this.getHash();
- }
- }
- return fragment.replace(routeStripper, '');
- },
-
- // Start the hash change handling, returning `true` if the current URL matches
- // an existing route, and `false` otherwise.
- start: function(options) {
- if (History.started) throw new Error("Backbone.history has already been started");
- History.started = true;
-
- // Figure out the initial configuration. Do we need an iframe?
- // Is pushState desired ... is it available?
- this.options = _.extend({root: '/'}, this.options, options);
- this.root = this.options.root;
- this._wantsHashChange = this.options.hashChange !== false;
- this._wantsPushState = !!this.options.pushState;
- this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
- var fragment = this.getFragment();
- var docMode = document.documentMode;
- var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
-
- // Normalize root to always include a leading and trailing slash.
- this.root = ('/' + this.root + '/').replace(rootStripper, '/');
-
- if (oldIE && this._wantsHashChange) {
- var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
- this.iframe = frame.hide().appendTo('body')[0].contentWindow;
- this.navigate(fragment);
- }
-
- // Depending on whether we're using pushState or hashes, and whether
- // 'onhashchange' is supported, determine how we check the URL state.
- if (this._hasPushState) {
- Backbone.$(window).on('popstate', this.checkUrl);
- } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
- Backbone.$(window).on('hashchange', this.checkUrl);
- } else if (this._wantsHashChange) {
- this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
- }
-
- // Determine if we need to change the base url, for a pushState link
- // opened by a non-pushState browser.
- this.fragment = fragment;
- var loc = this.location;
-
- // Transition from hashChange to pushState or vice versa if both are
- // requested.
- if (this._wantsHashChange && this._wantsPushState) {
-
- // If we've started off with a route from a `pushState`-enabled
- // browser, but we're currently in a browser that doesn't support it...
- if (!this._hasPushState && !this.atRoot()) {
- this.fragment = this.getFragment(null, true);
- this.location.replace(this.root + '#' + this.fragment);
- // Return immediately as browser will do redirect to new url
- return true;
-
- // Or if we've started out with a hash-based route, but we're currently
- // in a browser where it could be `pushState`-based instead...
- } else if (this._hasPushState && this.atRoot() && loc.hash) {
- this.fragment = this.getHash().replace(routeStripper, '');
- this.history.replaceState({}, document.title, this.root + this.fragment);
- }
-
- }
-
- if (!this.options.silent) return this.loadUrl();
- },
-
- // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
- // but possibly useful for unit testing Routers.
- stop: function() {
- Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
- if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
- History.started = false;
- },
-
- // Add a route to be tested when the fragment changes. Routes added later
- // may override previous routes.
- route: function(route, callback) {
- this.handlers.unshift({route: route, callback: callback});
- },
-
- // Checks the current URL to see if it has changed, and if it has,
- // calls `loadUrl`, normalizing across the hidden iframe.
- checkUrl: function(e) {
- var current = this.getFragment();
- if (current === this.fragment && this.iframe) {
- current = this.getFragment(this.getHash(this.iframe));
- }
- if (current === this.fragment) return false;
- if (this.iframe) this.navigate(current);
- this.loadUrl();
- },
-
- // Attempt to load the current URL fragment. If a route succeeds with a
- // match, returns `true`. If no defined routes matches the fragment,
- // returns `false`.
- loadUrl: function(fragment) {
- fragment = this.fragment = this.getFragment(fragment);
- return _.any(this.handlers, function(handler) {
- if (handler.route.test(fragment)) {
- handler.callback(fragment);
- return true;
- }
- });
- },
-
- // Save a fragment into the hash history, or replace the URL state if the
- // 'replace' option is passed. You are responsible for properly URL-encoding
- // the fragment in advance.
- //
- // The options object can contain `trigger: true` if you wish to have the
- // route callback be fired (not usually desirable), or `replace: true`, if
- // you wish to modify the current URL without adding an entry to the history.
- navigate: function(fragment, options) {
- if (!History.started) return false;
- if (!options || options === true) options = {trigger: !!options};
-
- var url = this.root + (fragment = this.getFragment(fragment || ''));
-
- // Strip the hash for matching.
- fragment = fragment.replace(pathStripper, '');
-
- if (this.fragment === fragment) return;
- this.fragment = fragment;
-
- // Don't include a trailing slash on the root.
- if (fragment === '' && url !== '/') url = url.slice(0, -1);
-
- // If pushState is available, we use it to set the fragment as a real URL.
- if (this._hasPushState) {
- this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
-
- // If hash changes haven't been explicitly disabled, update the hash
- // fragment to store history.
- } else if (this._wantsHashChange) {
- this._updateHash(this.location, fragment, options.replace);
- if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) {
- // Opening and closing the iframe tricks IE7 and earlier to push a
- // history entry on hash-tag change. When replace is true, we don't
- // want this.
- if(!options.replace) this.iframe.document.open().close();
- this._updateHash(this.iframe.location, fragment, options.replace);
- }
-
- // If you've told us that you explicitly don't want fallback hashchange-
- // based history, then `navigate` becomes a page refresh.
- } else {
- return this.location.assign(url);
- }
- if (options.trigger) return this.loadUrl(fragment);
- },
-
- // Update the hash location, either replacing the current entry, or adding
- // a new one to the browser history.
- _updateHash: function(location, fragment, replace) {
- if (replace) {
- var href = location.href.replace(/(javascript:|#).*$/, '');
- location.replace(href + '#' + fragment);
- } else {
- // Some browsers require that `hash` contains a leading #.
- location.hash = '#' + fragment;
- }
- }
-
- });
-
- // Create the default Backbone.history.
- Backbone.history = new History;
-
- // Helpers
- // -------
-
- // Helper function to correctly set up the prototype chain, for subclasses.
- // Similar to `goog.inherits`, but uses a hash of prototype properties and
- // class properties to be extended.
- var extend = function(protoProps, staticProps) {
- var parent = this;
- var child;
-
- // The constructor function for the new subclass is either defined by you
- // (the "constructor" property in your `extend` definition), or defaulted
- // by us to simply call the parent's constructor.
- if (protoProps && _.has(protoProps, 'constructor')) {
- child = protoProps.constructor;
- } else {
- child = function(){ return parent.apply(this, arguments); };
- }
-
- // Add static properties to the constructor function, if supplied.
- _.extend(child, parent, staticProps);
-
- // Set the prototype chain to inherit from `parent`, without calling
- // `parent`'s constructor function.
- var Surrogate = function(){ this.constructor = child; };
- Surrogate.prototype = parent.prototype;
- child.prototype = new Surrogate;
-
- // Add prototype properties (instance properties) to the subclass,
- // if supplied.
- if (protoProps) _.extend(child.prototype, protoProps);
-
- // Set a convenience property in case the parent's prototype is needed
- // later.
- child.__super__ = parent.prototype;
-
- return child;
- };
-
- // Set up inheritance for the model, collection, router, view and history.
- Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
-
- // Throw an error when a URL is needed, and none is supplied.
- var urlError = function() {
- throw new Error('A "url" property or function must be specified');
- };
-
- // Wrap an optional error callback with a fallback error event.
- var wrapError = function(model, options) {
- var error = options.error;
- options.error = function(resp) {
- if (error) error(model, resp, options);
- model.trigger('error', model, resp, options);
- };
- };
-
- return Backbone;
-
-}));
\ No newline at end of file
[13/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/js/backbone.marionette-2.4.1.min.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/js/backbone.marionette-2.4.1.min.js b/htrace-htraced/src/web/lib/js/backbone.marionette-2.4.1.min.js
deleted file mode 100644
index 994efee..0000000
--- a/htrace-htraced/src/web/lib/js/backbone.marionette-2.4.1.min.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// MarionetteJS (Backbone.Marionette)
-// ----------------------------------
-// v2.4.1
-//
-// Copyright (c)2015 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://marionettejs.com
-
-
-/*!
- * Includes BabySitter
- * https://github.com/marionettejs/backbone.babysitter/
- *
- * Includes Wreqr
- * https://github.com/marionettejs/backbone.wreqr/
- */
-
-
-
-!function(a,b){if("function"==typeof define&&define.amd)define(["backbone","underscore"],function(c,d){return a.Marionette=a.Mn=b(a,c,d)});else if("undefined"!=typeof exports){var c=require("backbone"),d=require("underscore");module.exports=b(a,c,d)}else a.Marionette=a.Mn=b(a,a.Backbone,a._)}(this,function(a,b,c){"use strict";!function(a,b){var c=a.ChildViewContainer;return a.ChildViewContainer=function(a,b){var c=function(a){this._views={},this._indexByModel={},this._indexByCustom={},this._updateLength(),b.each(a,this.add,this)};b.extend(c.prototype,{add:function(a,b){var c=a.cid;return this._views[c]=a,a.model&&(this._indexByModel[a.model.cid]=c),b&&(this._indexByCustom[b]=c),this._updateLength(),this},findByModel:function(a){return this.findByModelCid(a.cid)},findByModelCid:function(a){var b=this._indexByModel[a];return this.findByCid(b)},findByCustom:function(a){var b=this._indexByCustom[a];return this.findByCid(b)},findByIndex:function(a){return b.values(this._views)[a]},findBy
Cid:function(a){return this._views[a]},remove:function(a){var c=a.cid;return a.model&&delete this._indexByModel[a.model.cid],b.any(this._indexByCustom,function(a,b){return a===c?(delete this._indexByCustom[b],!0):void 0},this),delete this._views[c],this._updateLength(),this},call:function(a){this.apply(a,b.tail(arguments))},apply:function(a,c){b.each(this._views,function(d){b.isFunction(d[a])&&d[a].apply(d,c||[])})},_updateLength:function(){this.length=b.size(this._views)}});var d=["forEach","each","map","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","toArray","first","initial","rest","last","without","isEmpty","pluck","reduce"];return b.each(d,function(a){c.prototype[a]=function(){var c=b.values(this._views),d=[c].concat(b.toArray(arguments));return b[a].apply(b,d)}}),c}(a,b),a.ChildViewContainer.VERSION="0.1.6",a.ChildViewContainer.noConflict=function(){return a.ChildViewContainer=c,this},a.ChildViewContainer}(b,c),function(a,b)
{var c=a.Wreqr,d=a.Wreqr={};return a.Wreqr.VERSION="1.3.1",a.Wreqr.noConflict=function(){return a.Wreqr=c,this},d.Handlers=function(a,b){var c=function(a){this.options=a,this._wreqrHandlers={},b.isFunction(this.initialize)&&this.initialize(a)};return c.extend=a.Model.extend,b.extend(c.prototype,a.Events,{setHandlers:function(a){b.each(a,function(a,c){var d=null;b.isObject(a)&&!b.isFunction(a)&&(d=a.context,a=a.callback),this.setHandler(c,a,d)},this)},setHandler:function(a,b,c){var d={callback:b,context:c};this._wreqrHandlers[a]=d,this.trigger("handler:add",a,b,c)},hasHandler:function(a){return!!this._wreqrHandlers[a]},getHandler:function(a){var b=this._wreqrHandlers[a];if(b)return function(){var a=Array.prototype.slice.apply(arguments);return b.callback.apply(b.context,a)}},removeHandler:function(a){delete this._wreqrHandlers[a]},removeAllHandlers:function(){this._wreqrHandlers={}}}),c}(a,b),d.CommandStorage=function(){var c=function(a){this.options=a,this._commands={},b.isFunction(
this.initialize)&&this.initialize(a)};return b.extend(c.prototype,a.Events,{getCommands:function(a){var b=this._commands[a];return b||(b={command:a,instances:[]},this._commands[a]=b),b},addCommand:function(a,b){var c=this.getCommands(a);c.instances.push(b)},clearCommands:function(a){var b=this.getCommands(a);b.instances=[]}}),c}(),d.Commands=function(a){return a.Handlers.extend({storageType:a.CommandStorage,constructor:function(b){this.options=b||{},this._initializeStorage(this.options),this.on("handler:add",this._executeCommands,this);var c=Array.prototype.slice.call(arguments);a.Handlers.prototype.constructor.apply(this,c)},execute:function(a,b){a=arguments[0],b=Array.prototype.slice.call(arguments,1),this.hasHandler(a)?this.getHandler(a).apply(this,b):this.storage.addCommand(a,b)},_executeCommands:function(a,c,d){var e=this.storage.getCommands(a);b.each(e.instances,function(a){c.apply(d,a)}),this.storage.clearCommands(a)},_initializeStorage:function(a){var c,d=a.storageType||this
.storageType;c=b.isFunction(d)?new d:d,this.storage=c}})}(d),d.RequestResponse=function(a){return a.Handlers.extend({request:function(){var a=arguments[0],b=Array.prototype.slice.call(arguments,1);return this.hasHandler(a)?this.getHandler(a).apply(this,b):void 0}})}(d),d.EventAggregator=function(a,b){var c=function(){};return c.extend=a.Model.extend,b.extend(c.prototype,a.Events),c}(a,b),d.Channel=function(){var c=function(b){this.vent=new a.Wreqr.EventAggregator,this.reqres=new a.Wreqr.RequestResponse,this.commands=new a.Wreqr.Commands,this.channelName=b};return b.extend(c.prototype,{reset:function(){return this.vent.off(),this.vent.stopListening(),this.reqres.removeAllHandlers(),this.commands.removeAllHandlers(),this},connectEvents:function(a,b){return this._connect("vent",a,b),this},connectCommands:function(a,b){return this._connect("commands",a,b),this},connectRequests:function(a,b){return this._connect("reqres",a,b),this},_connect:function(a,c,d){if(c){d=d||this;var e="vent"===
a?"on":"setHandler";b.each(c,function(c,f){this[a][e](f,b.bind(c,d))},this)}}}),c}(d),d.radio=function(a){var c=function(){this._channels={},this.vent={},this.commands={},this.reqres={},this._proxyMethods()};b.extend(c.prototype,{channel:function(a){if(!a)throw new Error("Channel must receive a name");return this._getChannel(a)},_getChannel:function(b){var c=this._channels[b];return c||(c=new a.Channel(b),this._channels[b]=c),c},_proxyMethods:function(){b.each(["vent","commands","reqres"],function(a){b.each(d[a],function(b){this[a][b]=e(this,a,b)},this)},this)}});var d={vent:["on","off","trigger","once","stopListening","listenTo","listenToOnce"],commands:["execute","setHandler","setHandlers","removeHandler","removeAllHandlers"],reqres:["request","setHandler","setHandlers","removeHandler","removeAllHandlers"]},e=function(a,b,c){return function(d){var e=a._getChannel(d)[b],f=Array.prototype.slice.call(arguments,1);return e[c].apply(e,f)}};return new c}(d),a.Wreqr}(b,c);var d=a.Marione
tte,e=a.Mn,f=b.Marionette={};f.VERSION="2.4.1",f.noConflict=function(){return a.Marionette=d,a.Mn=e,this},b.Marionette=f,f.Deferred=b.$.Deferred,f.extend=b.Model.extend,f.isNodeAttached=function(a){return b.$.contains(document.documentElement,a)},f.mergeOptions=function(a,b){a&&c.extend(this,c.pick(a,b))},f.getOption=function(a,b){return a&&b?a.options&&void 0!==a.options[b]?a.options[b]:a[b]:void 0},f.proxyGetOption=function(a){return f.getOption(this,a)},f._getValue=function(a,b,d){return c.isFunction(a)&&(a=d?a.apply(b,d):a.call(b)),a},f.normalizeMethods=function(a){return c.reduce(a,function(a,b,d){return c.isFunction(b)||(b=this[b]),b&&(a[d]=b),a},{},this)},f.normalizeUIString=function(a,b){return a.replace(/@ui\.[a-zA-Z_$0-9]*/g,function(a){return b[a.slice(4)]})},f.normalizeUIKeys=function(a,b){return c.reduce(a,function(a,c,d){var e=f.normalizeUIString(d,b);return a[e]=c,a},{})},f.normalizeUIValues=function(a,b,d){return c.each(a,function(e,g){c.isString(e)?a[g]=f.normalizeU
IString(e,b):c.isObject(e)&&c.isArray(d)&&(c.extend(e,f.normalizeUIValues(c.pick(e,d),b)),c.each(d,function(a){var d=e[a];c.isString(d)&&(e[a]=f.normalizeUIString(d,b))}))}),a},f.actAsCollection=function(a,b){var d=["forEach","each","map","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","toArray","first","initial","rest","last","without","isEmpty","pluck"];c.each(d,function(d){a[d]=function(){var a=c.values(c.result(this,b)),e=[a].concat(c.toArray(arguments));return c[d].apply(c,e)}})};var g=f.deprecate=function(a,b){c.isObject(a)&&(a=a.prev+" is going to be removed in the future. Please use "+a.next+" instead."+(a.url?" See: "+a.url:"")),void 0!==b&&b||g._cache[a]||(g._warn("Deprecation warning: "+a),g._cache[a]=!0)};g._warn="undefined"!=typeof console&&(console.warn||console.log)||function(){},g._cache={},f._triggerMethod=function(){function a(a,b,c){return c.toUpperCase()}var b=/(^|:)(\w)/gi;return function(d,e,f){var g=arguments
.length<3;g&&(f=e,e=f[0]);var h,i="on"+e.replace(b,a),j=d[i];return c.isFunction(j)&&(h=j.apply(d,g?c.rest(f):f)),c.isFunction(d.trigger)&&(g+f.length>1?d.trigger.apply(d,g?f:[e].concat(c.drop(f,0))):d.trigger(e)),h}}(),f.triggerMethod=function(){return f._triggerMethod(this,arguments)},f.triggerMethodOn=function(a){var b=c.isFunction(a.triggerMethod)?a.triggerMethod:f.triggerMethod;return b.apply(a,c.rest(arguments))},f.MonitorDOMRefresh=function(a){function b(){a._isShown=!0,e()}function d(){a._isRendered=!0,e()}function e(){a._isShown&&a._isRendered&&f.isNodeAttached(a.el)&&c.isFunction(a.triggerMethod)&&a.triggerMethod("dom:refresh")}a.on({show:b,render:d})},function(a){function b(b,d,e,f){var g=f.split(/\s+/);c.each(g,function(c){var f=b[c];if(!f)throw new a.Error('Method "'+c+'" was configured as an event handler, but does not exist.');b.listenTo(d,e,f)})}function d(a,b,c,d){a.listenTo(b,c,d)}function e(a,b,d,e){var f=e.split(/\s+/);c.each(f,function(c){var e=a[c];a.stopListen
ing(b,d,e)})}function f(a,b,c,d){a.stopListening(b,c,d)}function g(b,d,e,f,g){if(d&&e){if(!c.isObject(e))throw new a.Error({message:"Bindings must be an object or function.",url:"marionette.functions.html#marionettebindentityevents"});e=a._getValue(e,b),c.each(e,function(a,e){c.isFunction(a)?f(b,d,e,a):g(b,d,e,a)})}}a.bindEntityEvents=function(a,c,e){g(a,c,e,d,b)},a.unbindEntityEvents=function(a,b,c){g(a,b,c,f,e)},a.proxyBindEntityEvents=function(b,c){return a.bindEntityEvents(this,b,c)},a.proxyUnbindEntityEvents=function(b,c){return a.unbindEntityEvents(this,b,c)}}(f);var h=["description","fileName","lineNumber","name","message","number"];return f.Error=f.extend.call(Error,{urlRoot:"http://marionettejs.com/docs/v"+f.VERSION+"/",constructor:function(a,b){c.isObject(a)?(b=a,a=b.message):b||(b={});var d=Error.call(this,a);c.extend(this,c.pick(d,h),c.pick(b,h)),this.captureStackTrace(),b.url&&(this.url=this.urlRoot+b.url)},captureStackTrace:function(){Error.captureStackTrace&&Error.cap
tureStackTrace(this,f.Error)},toString:function(){return this.name+": "+this.message+(this.url?" See: "+this.url:"")}}),f.Error.extend=f.extend,f.Callbacks=function(){this._deferred=f.Deferred(),this._callbacks=[]},c.extend(f.Callbacks.prototype,{add:function(a,b){var d=c.result(this._deferred,"promise");this._callbacks.push({cb:a,ctx:b}),d.then(function(c){b&&(c.context=b),a.call(c.context,c.options)})},run:function(a,b){this._deferred.resolve({options:a,context:b})},reset:function(){var a=this._callbacks;this._deferred=f.Deferred(),this._callbacks=[],c.each(a,function(a){this.add(a.cb,a.ctx)},this)}}),f.Controller=function(a){this.options=a||{},c.isFunction(this.initialize)&&this.initialize(this.options)},f.Controller.extend=f.extend,c.extend(f.Controller.prototype,b.Events,{destroy:function(){return f._triggerMethod(this,"before:destroy",arguments),f._triggerMethod(this,"destroy",arguments),this.stopListening(),this.off(),this},triggerMethod:f.triggerMethod,mergeOptions:f.mergeOp
tions,getOption:f.proxyGetOption}),f.Object=function(a){this.options=c.extend({},c.result(this,"options"),a),this.initialize.apply(this,arguments)},f.Object.extend=f.extend,c.extend(f.Object.prototype,b.Events,{initialize:function(){},destroy:function(){return this.triggerMethod("before:destroy"),this.triggerMethod("destroy"),this.stopListening(),this},triggerMethod:f.triggerMethod,mergeOptions:f.mergeOptions,getOption:f.proxyGetOption,bindEntityEvents:f.proxyBindEntityEvents,unbindEntityEvents:f.proxyUnbindEntityEvents}),f.Region=f.Object.extend({constructor:function(a){if(this.options=a||{},this.el=this.getOption("el"),this.el=this.el instanceof b.$?this.el[0]:this.el,!this.el)throw new f.Error({name:"NoElError",message:'An "el" must be specified for a region.'});this.$el=this.getEl(this.el),f.Object.call(this,a)},show:function(a,b){if(this._ensureElement()){this._ensureViewIsIntact(a);var c=b||{},d=a!==this.currentView,e=!!c.preventDestroy,g=!!c.forceShow,h=!!this.currentView,i=d
&&!e,j=d||g;if(h&&this.triggerMethod("before:swapOut",this.currentView,this,b),this.currentView&&delete this.currentView._parent,i?this.empty():h&&j&&this.currentView.off("destroy",this.empty,this),j){a.once("destroy",this.empty,this),a.render(),a._parent=this,h&&this.triggerMethod("before:swap",a,this,b),this.triggerMethod("before:show",a,this,b),f.triggerMethodOn(a,"before:show",a,this,b),h&&this.triggerMethod("swapOut",this.currentView,this,b);var k=f.isNodeAttached(this.el),l=[],m=c.triggerBeforeAttach||this.triggerBeforeAttach,n=c.triggerAttach||this.triggerAttach;return k&&m&&(l=this._displayedViews(a),this._triggerAttach(l,"before:")),this.attachHtml(a),this.currentView=a,k&&n&&(l=this._displayedViews(a),this._triggerAttach(l)),h&&this.triggerMethod("swap",a,this,b),this.triggerMethod("show",a,this,b),f.triggerMethodOn(a,"show",a,this,b),this}return this}},triggerBeforeAttach:!0,triggerAttach:!0,_triggerAttach:function(a,b){var d=(b||"")+"attach";c.each(a,function(a){f.trigge
rMethodOn(a,d,a,this)},this)},_displayedViews:function(a){return c.union([a],c.result(a,"_getNestedViews")||[])},_ensureElement:function(){if(c.isObject(this.el)||(this.$el=this.getEl(this.el),this.el=this.$el[0]),!this.$el||0===this.$el.length){if(this.getOption("allowMissingEl"))return!1;throw new f.Error('An "el" '+this.$el.selector+" must exist in DOM")}return!0},_ensureViewIsIntact:function(a){if(!a)throw new f.Error({name:"ViewNotValid",message:"The view passed is undefined and therefore invalid. You must pass a view instance to show."});if(a.isDestroyed)throw new f.Error({name:"ViewDestroyedError",message:'View (cid: "'+a.cid+'") has already been destroyed and cannot be used.'})},getEl:function(a){return b.$(a,f._getValue(this.options.parentEl,this))},attachHtml:function(a){this.$el.contents().detach(),this.el.appendChild(a.el)},empty:function(a){var b=this.currentView,c=f._getValue(a,"preventDestroy",this);return b?(b.off("destroy",this.empty,this),this.triggerMethod("before
:empty",b),c||this._destroyView(),this.triggerMethod("empty",b),delete this.currentView,c&&this.$el.contents().detach(),this):void 0},_destroyView:function(){var a=this.currentView;a.destroy&&!a.isDestroyed?a.destroy():a.remove&&(a.remove(),a.isDestroyed=!0)},attachView:function(a){return this.currentView=a,this},hasView:function(){return!!this.currentView},reset:function(){return this.empty(),this.$el&&(this.el=this.$el.selector),delete this.$el,this}},{buildRegion:function(a,b){if(c.isString(a))return this._buildRegionFromSelector(a,b);if(a.selector||a.el||a.regionClass)return this._buildRegionFromObject(a,b);if(c.isFunction(a))return this._buildRegionFromRegionClass(a);throw new f.Error({message:"Improper region configuration type.",url:"marionette.region.html#region-configuration-types"})},_buildRegionFromSelector:function(a,b){return new b({el:a})},_buildRegionFromObject:function(a,b){var d=a.regionClass||b,e=c.omit(a,"selector","regionClass");return a.selector&&!e.el&&(e.el=a.
selector),new d(e)},_buildRegionFromRegionClass:function(a){return new a}}),f.RegionManager=f.Controller.extend({constructor:function(a){this._regions={},this.length=0,f.Controller.call(this,a),this.addRegions(this.getOption("regions"))},addRegions:function(a,b){return a=f._getValue(a,this,arguments),c.reduce(a,function(a,d,e){return c.isString(d)&&(d={selector:d}),d.selector&&(d=c.defaults({},d,b)),a[e]=this.addRegion(e,d),a},{},this)},addRegion:function(a,b){var c;return c=b instanceof f.Region?b:f.Region.buildRegion(b,f.Region),this.triggerMethod("before:add:region",a,c),c._parent=this,this._store(a,c),this.triggerMethod("add:region",a,c),c},get:function(a){return this._regions[a]},getRegions:function(){return c.clone(this._regions)},removeRegion:function(a){var b=this._regions[a];return this._remove(a,b),b},removeRegions:function(){var a=this.getRegions();return c.each(this._regions,function(a,b){this._remove(b,a)},this),a},emptyRegions:function(){var a=this.getRegions();return
c.invoke(a,"empty"),a},destroy:function(){return this.removeRegions(),f.Controller.prototype.destroy.apply(this,arguments)},_store:function(a,b){this._regions[a]||this.length++,this._regions[a]=b},_remove:function(a,b){this.triggerMethod("before:remove:region",a,b),b.empty(),b.stopListening(),delete b._parent,delete this._regions[a],this.length--,this.triggerMethod("remove:region",a,b)}}),f.actAsCollection(f.RegionManager.prototype,"_regions"),f.TemplateCache=function(a){this.templateId=a},c.extend(f.TemplateCache,{templateCaches:{},get:function(a,b){var c=this.templateCaches[a];return c||(c=new f.TemplateCache(a),this.templateCaches[a]=c),c.load(b)},clear:function(){var a,b=c.toArray(arguments),d=b.length;if(d>0)for(a=0;d>a;a++)delete this.templateCaches[b[a]];else this.templateCaches={}}}),c.extend(f.TemplateCache.prototype,{load:function(a){if(this.compiledTemplate)return this.compiledTemplate;var b=this.loadTemplate(this.templateId,a);return this.compiledTemplate=this.compileTem
plate(b,a),this.compiledTemplate},loadTemplate:function(a){var c=b.$(a).html();if(!c||0===c.length)throw new f.Error({name:"NoTemplateError",message:'Could not find template: "'+a+'"'});return c},compileTemplate:function(a,b){return c.template(a,b)}}),f.Renderer={render:function(a,b){if(!a)throw new f.Error({name:"TemplateNotFoundError",message:"Cannot render the template since its false, null or undefined."});var d=c.isFunction(a)?a:f.TemplateCache.get(a);return d(b)}},f.View=b.View.extend({isDestroyed:!1,constructor:function(a){c.bindAll(this,"render"),a=f._getValue(a,this),this.options=c.extend({},c.result(this,"options"),a),this._behaviors=f.Behaviors(this),b.View.call(this,this.options),f.MonitorDOMRefresh(this)},getTemplate:function(){return this.getOption("template")},serializeModel:function(a){return a.toJSON.apply(a,c.rest(arguments))},mixinTemplateHelpers:function(a){a=a||{};var b=this.getOption("templateHelpers");return b=f._getValue(b,this),c.extend(a,b)},normalizeUIKeys
:function(a){var b=c.result(this,"_uiBindings");return f.normalizeUIKeys(a,b||c.result(this,"ui"))},normalizeUIValues:function(a,b){var d=c.result(this,"ui"),e=c.result(this,"_uiBindings");return f.normalizeUIValues(a,e||d,b)},configureTriggers:function(){if(this.triggers){var a=this.normalizeUIKeys(c.result(this,"triggers"));return c.reduce(a,function(a,b,c){return a[c]=this._buildViewTrigger(b),a},{},this)}},delegateEvents:function(a){return this._delegateDOMEvents(a),this.bindEntityEvents(this.model,this.getOption("modelEvents")),this.bindEntityEvents(this.collection,this.getOption("collectionEvents")),c.each(this._behaviors,function(a){a.bindEntityEvents(this.model,a.getOption("modelEvents")),a.bindEntityEvents(this.collection,a.getOption("collectionEvents"))},this),this},_delegateDOMEvents:function(a){var d=f._getValue(a||this.events,this);d=this.normalizeUIKeys(d),c.isUndefined(a)&&(this.events=d);var e={},g=c.result(this,"behaviorEvents")||{},h=this.configureTriggers(),i=c.re
sult(this,"behaviorTriggers")||{};c.extend(e,g,d,h,i),b.View.prototype.delegateEvents.call(this,e)},undelegateEvents:function(){return b.View.prototype.undelegateEvents.apply(this,arguments),this.unbindEntityEvents(this.model,this.getOption("modelEvents")),this.unbindEntityEvents(this.collection,this.getOption("collectionEvents")),c.each(this._behaviors,function(a){a.unbindEntityEvents(this.model,a.getOption("modelEvents")),a.unbindEntityEvents(this.collection,a.getOption("collectionEvents"))},this),this},_ensureViewIsIntact:function(){if(this.isDestroyed)throw new f.Error({name:"ViewDestroyedError",message:'View (cid: "'+this.cid+'") has already been destroyed and cannot be used.'})},destroy:function(){if(this.isDestroyed)return this;var a=c.toArray(arguments);return this.triggerMethod.apply(this,["before:destroy"].concat(a)),this.isDestroyed=!0,this.triggerMethod.apply(this,["destroy"].concat(a)),this.unbindUIElements(),this.isRendered=!1,this.remove(),c.invoke(this._behaviors,"de
stroy",a),this},bindUIElements:function(){this._bindUIElements(),c.invoke(this._behaviors,this._bindUIElements)},_bindUIElements:function(){if(this.ui){this._uiBindings||(this._uiBindings=this.ui);var a=c.result(this,"_uiBindings");this.ui={},c.each(a,function(a,b){this.ui[b]=this.$(a)},this)}},unbindUIElements:function(){this._unbindUIElements(),c.invoke(this._behaviors,this._unbindUIElements)},_unbindUIElements:function(){this.ui&&this._uiBindings&&(c.each(this.ui,function(a,b){delete this.ui[b]},this),this.ui=this._uiBindings,delete this._uiBindings)},_buildViewTrigger:function(a){var b=c.isObject(a),d=c.defaults({},b?a:{},{preventDefault:!0,stopPropagation:!0}),e=b?d.event:a;return function(a){a&&(a.preventDefault&&d.preventDefault&&a.preventDefault(),a.stopPropagation&&d.stopPropagation&&a.stopPropagation());var b={view:this,model:this.model,collection:this.collection};this.triggerMethod(e,b)}},setElement:function(){var a=b.View.prototype.setElement.apply(this,arguments);return
c.invoke(this._behaviors,"proxyViewProperties",this),a},triggerMethod:function(){var a=f._triggerMethod(this,arguments);return this._triggerEventOnBehaviors(arguments),this._triggerEventOnParentLayout(arguments[0],c.rest(arguments)),a},_triggerEventOnBehaviors:function(a){for(var b=f._triggerMethod,c=this._behaviors,d=0,e=c&&c.length;e>d;d++)b(c[d],a)},_triggerEventOnParentLayout:function(a,b){var d=this._parentLayoutView();if(d){var e=f.getOption(d,"childViewEventPrefix"),g=e+":"+a;f._triggerMethod(d,[g,this].concat(b));var h=f.getOption(d,"childEvents"),i=d.normalizeMethods(h);i&&c.isFunction(i[a])&&i[a].apply(d,[this].concat(b))}},_getImmediateChildren:function(){return[]},_getNestedViews:function(){var a=this._getImmediateChildren();return a.length?c.reduce(a,function(a,b){return b._getNestedViews?a.concat(b._getNestedViews()):a},a):a},_getAncestors:function(){for(var a=[],b=this._parent;b;)a.push(b),b=b._parent;return a},_parentLayoutView:function(){var a=this._getAncestors();
return c.find(a,function(a){return a instanceof f.LayoutView})},normalizeMethods:f.normalizeMethods,mergeOptions:f.mergeOptions,getOption:f.proxyGetOption,bindEntityEvents:f.proxyBindEntityEvents,unbindEntityEvents:f.proxyUnbindEntityEvents}),f.ItemView=f.View.extend({constructor:function(){f.View.apply(this,arguments)},serializeData:function(){if(!this.model&&!this.collection)return{};var a=[this.model||this.collection];return arguments.length&&a.push.apply(a,arguments),this.model?this.serializeModel.apply(this,a):{items:this.serializeCollection.apply(this,a)}},serializeCollection:function(a){return a.toJSON.apply(a,c.rest(arguments))},render:function(){return this._ensureViewIsIntact(),this.triggerMethod("before:render",this),this._renderTemplate(),this.isRendered=!0,this.bindUIElements(),this.triggerMethod("render",this),this},_renderTemplate:function(){var a=this.getTemplate();if(a!==!1){if(!a)throw new f.Error({name:"UndefinedTemplateError",message:"Cannot render the template s
ince it is null or undefined."});var b=this.mixinTemplateHelpers(this.serializeData()),c=f.Renderer.render(a,b,this);return this.attachElContent(c),this}},attachElContent:function(a){return this.$el.html(a),this}}),f.CollectionView=f.View.extend({childViewEventPrefix:"childview",sort:!0,constructor:function(){this.once("render",this._initialEvents),this._initChildViewStorage(),f.View.apply(this,arguments),this.on("show",this._onShowCalled),this.initRenderBuffer()},initRenderBuffer:function(){this._bufferedChildren=[]},startBuffering:function(){this.initRenderBuffer(),this.isBuffering=!0},endBuffering:function(){this.isBuffering=!1,this._triggerBeforeShowBufferedChildren(),this.attachBuffer(this),this._triggerShowBufferedChildren(),this.initRenderBuffer()},_triggerBeforeShowBufferedChildren:function(){this._isShown&&c.each(this._bufferedChildren,c.partial(this._triggerMethodOnChild,"before:show"))},_triggerShowBufferedChildren:function(){this._isShown&&(c.each(this._bufferedChildren,
c.partial(this._triggerMethodOnChild,"show")),this._bufferedChildren=[])},_triggerMethodOnChild:function(a,b){f.triggerMethodOn(b,a)},_initialEvents:function(){this.collection&&(this.listenTo(this.collection,"add",this._onCollectionAdd),this.listenTo(this.collection,"remove",this._onCollectionRemove),this.listenTo(this.collection,"reset",this.render),this.getOption("sort")&&this.listenTo(this.collection,"sort",this._sortViews))},_onCollectionAdd:function(a,b,d){var e;if(e=void 0!==d.at?d.at:c.indexOf(this._filteredSortedModels(),a),this._shouldAddChild(a,e)){this.destroyEmptyView();var f=this.getChildView(a);this.addChild(a,f,e)}},_onCollectionRemove:function(a){var b=this.children.findByModel(a);this.removeChildView(b),this.checkEmpty()},_onShowCalled:function(){this.children.each(c.partial(this._triggerMethodOnChild,"show"))},render:function(){return this._ensureViewIsIntact(),this.triggerMethod("before:render",this),this._renderChildren(),this.isRendered=!0,this.triggerMethod("re
nder",this),this},reorder:function(){var a=this.children,b=this._filteredSortedModels(),d=c.find(b,function(b){return!a.findByModel(b)});if(d)this.render();else{var e=c.map(b,function(b){return a.findByModel(b).el});this.triggerMethod("before:reorder"),this._appendReorderedChildren(e),this.triggerMethod("reorder")}},resortView:function(){f.getOption(this,"reorderOnSort")?this.reorder():this.render()},_sortViews:function(){var a=this._filteredSortedModels(),b=c.find(a,function(a,b){var c=this.children.findByModel(a);return!c||c._index!==b},this);b&&this.resortView()},_emptyViewIndex:-1,_appendReorderedChildren:function(a){this.$el.append(a)},_renderChildren:function(){this.destroyEmptyView(),this.destroyChildren(),this.isEmpty(this.collection)?this.showEmptyView():(this.triggerMethod("before:render:collection",this),this.startBuffering(),this.showCollection(),this.endBuffering(),this.triggerMethod("render:collection",this),this.children.isEmpty()&&this.showEmptyView())},showCollectio
n:function(){var a,b=this._filteredSortedModels();c.each(b,function(b,c){a=this.getChildView(b),this.addChild(b,a,c)},this)},_filteredSortedModels:function(){var a,b=this.getViewComparator();return a=b?c.isString(b)||1===b.length?this.collection.sortBy(b,this):c.clone(this.collection.models).sort(c.bind(b,this)):this.collection.models,this.getOption("filter")&&(a=c.filter(a,function(a,b){return this._shouldAddChild(a,b)},this)),a},showEmptyView:function(){var a=this.getEmptyView();if(a&&!this._showingEmptyView){this.triggerMethod("before:render:empty"),this._showingEmptyView=!0;var c=new b.Model;this.addEmptyView(c,a),this.triggerMethod("render:empty")}},destroyEmptyView:function(){this._showingEmptyView&&(this.triggerMethod("before:remove:empty"),this.destroyChildren(),delete this._showingEmptyView,this.triggerMethod("remove:empty"))},getEmptyView:function(){return this.getOption("emptyView")},addEmptyView:function(a,b){var d=this.getOption("emptyViewOptions")||this.getOption("chil
dViewOptions");c.isFunction(d)&&(d=d.call(this,a,this._emptyViewIndex));var e=this.buildChildView(a,b,d);e._parent=this,this.proxyChildEvents(e),this._isShown&&f.triggerMethodOn(e,"before:show"),this.children.add(e),this.renderChildView(e,this._emptyViewIndex),this._isShown&&f.triggerMethodOn(e,"show")},getChildView:function(){var a=this.getOption("childView");if(!a)throw new f.Error({name:"NoChildViewError",message:'A "childView" must be specified'});return a},addChild:function(a,b,c){var d=this.getOption("childViewOptions");d=f._getValue(d,this,[a,c]);var e=this.buildChildView(a,b,d);return this._updateIndices(e,!0,c),this._addChildView(e,c),e._parent=this,e},_updateIndices:function(a,b,c){this.getOption("sort")&&(b&&(a._index=c),this.children.each(function(c){c._index>=a._index&&(c._index+=b?1:-1)}))},_addChildView:function(a,b){this.proxyChildEvents(a),this.triggerMethod("before:add:child",a),this._isShown&&!this.isBuffering&&f.triggerMethodOn(a,"before:show"),this.children.add(
a),this.renderChildView(a,b),this._isShown&&!this.isBuffering&&f.triggerMethodOn(a,"show"),this.triggerMethod("add:child",a)},renderChildView:function(a,b){return a.render(),this.attachHtml(this,a,b),a},buildChildView:function(a,b,d){var e=c.extend({model:a},d);return new b(e)},removeChildView:function(a){return a&&(this.triggerMethod("before:remove:child",a),a.destroy?a.destroy():a.remove&&a.remove(),delete a._parent,this.stopListening(a),this.children.remove(a),this.triggerMethod("remove:child",a),this._updateIndices(a,!1)),a},isEmpty:function(){return!this.collection||0===this.collection.length},checkEmpty:function(){this.isEmpty(this.collection)&&this.showEmptyView()},attachBuffer:function(a){a.$el.append(this._createBuffer(a))},_createBuffer:function(a){var b=document.createDocumentFragment();return c.each(a._bufferedChildren,function(a){b.appendChild(a.el)}),b},attachHtml:function(a,b,c){a.isBuffering?a._bufferedChildren.splice(c,0,b):a._insertBefore(b,c)||a._insertAfter(b)},_
insertBefore:function(a,b){var c,d=this.getOption("sort")&&b<this.children.length-1;return d&&(c=this.children.find(function(a){return a._index===b+1})),c?(c.$el.before(a.el),!0):!1},_insertAfter:function(a){this.$el.append(a.el)},_initChildViewStorage:function(){this.children=new b.ChildViewContainer},destroy:function(){return this.isDestroyed?this:(this.triggerMethod("before:destroy:collection"),this.destroyChildren(),this.triggerMethod("destroy:collection"),f.View.prototype.destroy.apply(this,arguments))},destroyChildren:function(){var a=this.children.map(c.identity);return this.children.each(this.removeChildView,this),this.checkEmpty(),a},_shouldAddChild:function(a,b){var d=this.getOption("filter");return!c.isFunction(d)||d.call(this,a,b,this.collection)},proxyChildEvents:function(a){var b=this.getOption("childViewEventPrefix");this.listenTo(a,"all",function(){var d=c.toArray(arguments),e=d[0],f=this.normalizeMethods(c.result(this,"childEvents"));d[0]=b+":"+e,d.splice(1,0,a),"un
defined"!=typeof f&&c.isFunction(f[e])&&f[e].apply(this,d.slice(1)),this.triggerMethod.apply(this,d)})},_getImmediateChildren:function(){return c.values(this.children._views)},getViewComparator:function(){return this.getOption("viewComparator")}}),f.CompositeView=f.CollectionView.extend({constructor:function(){f.CollectionView.apply(this,arguments)},_initialEvents:function(){this.collection&&(this.listenTo(this.collection,"add",this._onCollectionAdd),this.listenTo(this.collection,"remove",this._onCollectionRemove),this.listenTo(this.collection,"reset",this._renderChildren),this.getOption("sort")&&this.listenTo(this.collection,"sort",this._sortViews))},getChildView:function(){var a=this.getOption("childView")||this.constructor;return a},serializeData:function(){var a={};return this.model&&(a=c.partial(this.serializeModel,this.model).apply(this,arguments)),a},render:function(){return this._ensureViewIsIntact(),this._isRendering=!0,this.resetChildViewContainer(),this.triggerMethod("bef
ore:render",this),this._renderTemplate(),this._renderChildren(),this._isRendering=!1,this.isRendered=!0,this.triggerMethod("render",this),this},_renderChildren:function(){(this.isRendered||this._isRendering)&&f.CollectionView.prototype._renderChildren.call(this)},_renderTemplate:function(){var a={};a=this.serializeData(),a=this.mixinTemplateHelpers(a),this.triggerMethod("before:render:template");var b=this.getTemplate(),c=f.Renderer.render(b,a,this);this.attachElContent(c),this.bindUIElements(),this.triggerMethod("render:template")},attachElContent:function(a){return this.$el.html(a),this},attachBuffer:function(a){var b=this.getChildViewContainer(a);b.append(this._createBuffer(a))},_insertAfter:function(a){var b=this.getChildViewContainer(this,a);b.append(a.el)},_appendReorderedChildren:function(a){var b=this.getChildViewContainer(this);b.append(a)},getChildViewContainer:function(a){if("$childViewContainer"in a)return a.$childViewContainer;var b,c=f.getOption(a,"childViewContainer")
;if(c){var d=f._getValue(c,a);if(b="@"===d.charAt(0)&&a.ui?a.ui[d.substr(4)]:a.$(d),b.length<=0)throw new f.Error({name:"ChildViewContainerMissingError",message:'The specified "childViewContainer" was not found: '+a.childViewContainer})
-}else b=a.$el;return a.$childViewContainer=b,b},resetChildViewContainer:function(){this.$childViewContainer&&delete this.$childViewContainer}}),f.LayoutView=f.ItemView.extend({regionClass:f.Region,options:{destroyImmediate:!1},childViewEventPrefix:"childview",constructor:function(a){a=a||{},this._firstRender=!0,this._initializeRegions(a),f.ItemView.call(this,a)},render:function(){return this._ensureViewIsIntact(),this._firstRender?this._firstRender=!1:this._reInitializeRegions(),f.ItemView.prototype.render.apply(this,arguments)},destroy:function(){return this.isDestroyed?this:(this.getOption("destroyImmediate")===!0&&this.$el.remove(),this.regionManager.destroy(),f.ItemView.prototype.destroy.apply(this,arguments))},showChildView:function(a,b){return this.getRegion(a).show(b)},getChildView:function(a){return this.getRegion(a).currentView},addRegion:function(a,b){var c={};return c[a]=b,this._buildRegions(c)[a]},addRegions:function(a){return this.regions=c.extend({},this.regions,a),thi
s._buildRegions(a)},removeRegion:function(a){return delete this.regions[a],this.regionManager.removeRegion(a)},getRegion:function(a){return this.regionManager.get(a)},getRegions:function(){return this.regionManager.getRegions()},_buildRegions:function(a){var b={regionClass:this.getOption("regionClass"),parentEl:c.partial(c.result,this,"el")};return this.regionManager.addRegions(a,b)},_initializeRegions:function(a){var b;this._initRegionManager(),b=f._getValue(this.regions,this,[a])||{};var d=this.getOption.call(a,"regions");d=f._getValue(d,this,[a]),c.extend(b,d),b=this.normalizeUIValues(b,["selector","el"]),this.addRegions(b)},_reInitializeRegions:function(){this.regionManager.invoke("reset")},getRegionManager:function(){return new f.RegionManager},_initRegionManager:function(){this.regionManager=this.getRegionManager(),this.regionManager._parent=this,this.listenTo(this.regionManager,"before:add:region",function(a){this.triggerMethod("before:add:region",a)}),this.listenTo(this.regi
onManager,"add:region",function(a,b){this[a]=b,this.triggerMethod("add:region",a,b)}),this.listenTo(this.regionManager,"before:remove:region",function(a){this.triggerMethod("before:remove:region",a)}),this.listenTo(this.regionManager,"remove:region",function(a,b){delete this[a],this.triggerMethod("remove:region",a,b)})},_getImmediateChildren:function(){return c.chain(this.regionManager.getRegions()).pluck("currentView").compact().value()}}),f.Behavior=f.Object.extend({constructor:function(a,b){this.view=b,this.defaults=c.result(this,"defaults")||{},this.options=c.extend({},this.defaults,a),this.ui=c.extend({},c.result(b,"ui"),c.result(this,"ui")),f.Object.apply(this,arguments)},$:function(){return this.view.$.apply(this.view,arguments)},destroy:function(){return this.stopListening(),this},proxyViewProperties:function(a){this.$el=a.$el,this.el=a.el}}),f.Behaviors=function(a,b){function c(a,d){return b.isObject(a.behaviors)?(d=c.parseBehaviors(a,d||b.result(a,"behaviors")),c.wrap(a,d,
b.keys(g)),d):{}}function d(a,b){this._view=a,this._behaviors=b,this._triggers={}}function e(a){return a._uiBindings||a.ui}var f=/^(\S+)\s*(.*)$/,g={behaviorTriggers:function(a,b){var c=new d(this,b);return c.buildBehaviorTriggers()},behaviorEvents:function(c,d){var g={};return b.each(d,function(c,d){var h={},i=b.clone(b.result(c,"events"))||{};i=a.normalizeUIKeys(i,e(c));var j=0;b.each(i,function(a,e){var g=e.match(f),i=g[1]+"."+[this.cid,d,j++," "].join(""),k=g[2],l=i+k,m=b.isFunction(a)?a:c[a];h[l]=b.bind(m,c)},this),g=b.extend(g,h)},this),g}};return b.extend(c,{behaviorsLookup:function(){throw new a.Error({message:"You must define where your behaviors are stored.",url:"marionette.behaviors.html#behaviorslookup"})},getBehaviorClass:function(b,d){return b.behaviorClass?b.behaviorClass:a._getValue(c.behaviorsLookup,this,[b,d])[d]},parseBehaviors:function(a,d){return b.chain(d).map(function(d,e){var f=c.getBehaviorClass(d,e),g=new f(d,a),h=c.parseBehaviors(a,b.result(g,"behaviors"))
;return[g].concat(h)}).flatten().value()},wrap:function(a,c,d){b.each(d,function(d){a[d]=b.partial(g[d],a[d],c)})}}),b.extend(d.prototype,{buildBehaviorTriggers:function(){return b.each(this._behaviors,this._buildTriggerHandlersForBehavior,this),this._triggers},_buildTriggerHandlersForBehavior:function(c,d){var f=b.clone(b.result(c,"triggers"))||{};f=a.normalizeUIKeys(f,e(c)),b.each(f,b.bind(this._setHandlerForBehavior,this,c,d))},_setHandlerForBehavior:function(a,b,c,d){var e=d.replace(/^\S+/,function(a){return a+".behaviortriggers"+b});this._triggers[e]=this._view._buildViewTrigger(c)}}),c}(f,c),f.AppRouter=b.Router.extend({constructor:function(a){this.options=a||{},b.Router.apply(this,arguments);var c=this.getOption("appRoutes"),d=this._getController();this.processAppRoutes(d,c),this.on("route",this._processOnRoute,this)},appRoute:function(a,b){var c=this._getController();this._addAppRoute(c,a,b)},_processOnRoute:function(a,b){if(c.isFunction(this.onRoute)){var d=c.invert(this.ge
tOption("appRoutes"))[a];this.onRoute(a,d,b)}},processAppRoutes:function(a,b){if(b){var d=c.keys(b).reverse();c.each(d,function(c){this._addAppRoute(a,c,b[c])},this)}},_getController:function(){return this.getOption("controller")},_addAppRoute:function(a,b,d){var e=a[d];if(!e)throw new f.Error('Method "'+d+'" was not found on the controller');this.route(b,d,c.bind(e,a))},mergeOptions:f.mergeOptions,getOption:f.proxyGetOption,triggerMethod:f.triggerMethod,bindEntityEvents:f.proxyBindEntityEvents,unbindEntityEvents:f.proxyUnbindEntityEvents}),f.Application=f.Object.extend({constructor:function(a){this._initializeRegions(a),this._initCallbacks=new f.Callbacks,this.submodules={},c.extend(this,a),this._initChannel(),f.Object.call(this,a)},execute:function(){this.commands.execute.apply(this.commands,arguments)},request:function(){return this.reqres.request.apply(this.reqres,arguments)},addInitializer:function(a){this._initCallbacks.add(a)},start:function(a){this.triggerMethod("before:star
t",a),this._initCallbacks.run(a,this),this.triggerMethod("start",a)},addRegions:function(a){return this._regionManager.addRegions(a)},emptyRegions:function(){return this._regionManager.emptyRegions()},removeRegion:function(a){return this._regionManager.removeRegion(a)},getRegion:function(a){return this._regionManager.get(a)},getRegions:function(){return this._regionManager.getRegions()},module:function(a,b){var d=f.Module.getClass(b),e=c.toArray(arguments);return e.unshift(this),d.create.apply(d,e)},getRegionManager:function(){return new f.RegionManager},_initializeRegions:function(a){var b=c.isFunction(this.regions)?this.regions(a):this.regions||{};this._initRegionManager();var d=f.getOption(a,"regions");return c.isFunction(d)&&(d=d.call(this,a)),c.extend(b,d),this.addRegions(b),this},_initRegionManager:function(){this._regionManager=this.getRegionManager(),this._regionManager._parent=this,this.listenTo(this._regionManager,"before:add:region",function(){f._triggerMethod(this,"befor
e:add:region",arguments)}),this.listenTo(this._regionManager,"add:region",function(a,b){this[a]=b,f._triggerMethod(this,"add:region",arguments)}),this.listenTo(this._regionManager,"before:remove:region",function(){f._triggerMethod(this,"before:remove:region",arguments)}),this.listenTo(this._regionManager,"remove:region",function(a){delete this[a],f._triggerMethod(this,"remove:region",arguments)})},_initChannel:function(){this.channelName=c.result(this,"channelName")||"global",this.channel=c.result(this,"channel")||b.Wreqr.radio.channel(this.channelName),this.vent=c.result(this,"vent")||this.channel.vent,this.commands=c.result(this,"commands")||this.channel.commands,this.reqres=c.result(this,"reqres")||this.channel.reqres}}),f.Module=function(a,b,d){this.moduleName=a,this.options=c.extend({},this.options,d),this.initialize=d.initialize||this.initialize,this.submodules={},this._setupInitializersAndFinalizers(),this.app=b,c.isFunction(this.initialize)&&this.initialize(a,b,this.options)
},f.Module.extend=f.extend,c.extend(f.Module.prototype,b.Events,{startWithParent:!0,initialize:function(){},addInitializer:function(a){this._initializerCallbacks.add(a)},addFinalizer:function(a){this._finalizerCallbacks.add(a)},start:function(a){this._isInitialized||(c.each(this.submodules,function(b){b.startWithParent&&b.start(a)}),this.triggerMethod("before:start",a),this._initializerCallbacks.run(a,this),this._isInitialized=!0,this.triggerMethod("start",a))},stop:function(){this._isInitialized&&(this._isInitialized=!1,this.triggerMethod("before:stop"),c.invoke(this.submodules,"stop"),this._finalizerCallbacks.run(void 0,this),this._initializerCallbacks.reset(),this._finalizerCallbacks.reset(),this.triggerMethod("stop"))},addDefinition:function(a,b){this._runModuleDefinition(a,b)},_runModuleDefinition:function(a,d){if(a){var e=c.flatten([this,this.app,b,f,b.$,c,d]);a.apply(this,e)}},_setupInitializersAndFinalizers:function(){this._initializerCallbacks=new f.Callbacks,this._finalize
rCallbacks=new f.Callbacks},triggerMethod:f.triggerMethod}),c.extend(f.Module,{create:function(a,b,d){var e=a,f=c.drop(arguments,3);b=b.split(".");var g=b.length,h=[];return h[g-1]=d,c.each(b,function(b,c){var g=e;e=this._getModule(g,b,a,d),this._addModuleDefinition(g,e,h[c],f)},this),e},_getModule:function(a,b,d,e){var f=c.extend({},e),g=this.getClass(e),h=a[b];return h||(h=new g(b,d,f),a[b]=h,a.submodules[b]=h),h},getClass:function(a){var b=f.Module;return a?a.prototype instanceof b?a:a.moduleClass||b:b},_addModuleDefinition:function(a,b,c,d){var e=this._getDefine(c),f=this._getStartWithParent(c,b);e&&b.addDefinition(e,d),this._addStartWithParent(a,b,f)},_getStartWithParent:function(a,b){var d;return c.isFunction(a)&&a.prototype instanceof f.Module?(d=b.constructor.prototype.startWithParent,c.isUndefined(d)?!0:d):c.isObject(a)?(d=a.startWithParent,c.isUndefined(d)?!0:d):!0},_getDefine:function(a){return!c.isFunction(a)||a.prototype instanceof f.Module?c.isObject(a)?a.define:null:a
},_addStartWithParent:function(a,b,c){b.startWithParent=b.startWithParent&&c,b.startWithParent&&!b.startWithParentIsConfigured&&(b.startWithParentIsConfigured=!0,a.addInitializer(function(a){b.startWithParent&&b.start(a)}))}}),f});
-//# sourceMappingURL=backbone.marionette.min.js.map
\ No newline at end of file
[16/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/backbone-1.1.2.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/backbone-1.1.2.js b/htrace-htraced/src/web/lib/backbone-1.1.2.js
new file mode 100644
index 0000000..5da4943
--- /dev/null
+++ b/htrace-htraced/src/web/lib/backbone-1.1.2.js
@@ -0,0 +1,1608 @@
+// Backbone.js 1.1.2
+
+// (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+// Backbone may be freely distributed under the MIT license.
+// For all details and documentation:
+// http://backbonejs.org
+
+(function(root, factory) {
+
+ // Set up Backbone appropriately for the environment. Start with AMD.
+ if (typeof define === 'function' && define.amd) {
+ define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
+ // Export global even in AMD case in case this script is loaded with
+ // others that may still expect a global Backbone.
+ root.Backbone = factory(root, exports, _, $);
+ });
+
+ // Next for Node.js or CommonJS. jQuery may not be needed as a module.
+ } else if (typeof exports !== 'undefined') {
+ var _ = require('underscore');
+ factory(root, exports, _);
+
+ // Finally, as a browser global.
+ } else {
+ root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
+ }
+
+}(this, function(root, Backbone, _, $) {
+
+ // Initial Setup
+ // -------------
+
+ // Save the previous value of the `Backbone` variable, so that it can be
+ // restored later on, if `noConflict` is used.
+ var previousBackbone = root.Backbone;
+
+ // Create local references to array methods we'll want to use later.
+ var array = [];
+ var push = array.push;
+ var slice = array.slice;
+ var splice = array.splice;
+
+ // Current version of the library. Keep in sync with `package.json`.
+ Backbone.VERSION = '1.1.2';
+
+ // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
+ // the `$` variable.
+ Backbone.$ = $;
+
+ // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
+ // to its previous owner. Returns a reference to this Backbone object.
+ Backbone.noConflict = function() {
+ root.Backbone = previousBackbone;
+ return this;
+ };
+
+ // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
+ // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
+ // set a `X-Http-Method-Override` header.
+ Backbone.emulateHTTP = false;
+
+ // Turn on `emulateJSON` to support legacy servers that can't deal with direct
+ // `application/json` requests ... will encode the body as
+ // `application/x-www-form-urlencoded` instead and will send the model in a
+ // form param named `model`.
+ Backbone.emulateJSON = false;
+
+ // Backbone.Events
+ // ---------------
+
+ // A module that can be mixed in to *any object* in order to provide it with
+ // custom events. You may bind with `on` or remove with `off` callback
+ // functions to an event; `trigger`-ing an event fires all callbacks in
+ // succession.
+ //
+ // var object = {};
+ // _.extend(object, Backbone.Events);
+ // object.on('expand', function(){ alert('expanded'); });
+ // object.trigger('expand');
+ //
+ var Events = Backbone.Events = {
+
+ // Bind an event to a `callback` function. Passing `"all"` will bind
+ // the callback to all events fired.
+ on: function(name, callback, context) {
+ if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
+ this._events || (this._events = {});
+ var events = this._events[name] || (this._events[name] = []);
+ events.push({callback: callback, context: context, ctx: context || this});
+ return this;
+ },
+
+ // Bind an event to only be triggered a single time. After the first time
+ // the callback is invoked, it will be removed.
+ once: function(name, callback, context) {
+ if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
+ var self = this;
+ var once = _.once(function() {
+ self.off(name, once);
+ callback.apply(this, arguments);
+ });
+ once._callback = callback;
+ return this.on(name, once, context);
+ },
+
+ // Remove one or many callbacks. If `context` is null, removes all
+ // callbacks with that function. If `callback` is null, removes all
+ // callbacks for the event. If `name` is null, removes all bound
+ // callbacks for all events.
+ off: function(name, callback, context) {
+ var retain, ev, events, names, i, l, j, k;
+ if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
+ if (!name && !callback && !context) {
+ this._events = void 0;
+ return this;
+ }
+ names = name ? [name] : _.keys(this._events);
+ for (i = 0, l = names.length; i < l; i++) {
+ name = names[i];
+ if (events = this._events[name]) {
+ this._events[name] = retain = [];
+ if (callback || context) {
+ for (j = 0, k = events.length; j < k; j++) {
+ ev = events[j];
+ if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
+ (context && context !== ev.context)) {
+ retain.push(ev);
+ }
+ }
+ }
+ if (!retain.length) delete this._events[name];
+ }
+ }
+
+ return this;
+ },
+
+ // Trigger one or many events, firing all bound callbacks. Callbacks are
+ // passed the same arguments as `trigger` is, apart from the event name
+ // (unless you're listening on `"all"`, which will cause your callback to
+ // receive the true name of the event as the first argument).
+ trigger: function(name) {
+ if (!this._events) return this;
+ var args = slice.call(arguments, 1);
+ if (!eventsApi(this, 'trigger', name, args)) return this;
+ var events = this._events[name];
+ var allEvents = this._events.all;
+ if (events) triggerEvents(events, args);
+ if (allEvents) triggerEvents(allEvents, arguments);
+ return this;
+ },
+
+ // Tell this object to stop listening to either specific events ... or
+ // to every object it's currently listening to.
+ stopListening: function(obj, name, callback) {
+ var listeningTo = this._listeningTo;
+ if (!listeningTo) return this;
+ var remove = !name && !callback;
+ if (!callback && typeof name === 'object') callback = this;
+ if (obj) (listeningTo = {})[obj._listenId] = obj;
+ for (var id in listeningTo) {
+ obj = listeningTo[id];
+ obj.off(name, callback, this);
+ if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
+ }
+ return this;
+ }
+
+ };
+
+ // Regular expression used to split event strings.
+ var eventSplitter = /\s+/;
+
+ // Implement fancy features of the Events API such as multiple event
+ // names `"change blur"` and jQuery-style event maps `{change: action}`
+ // in terms of the existing API.
+ var eventsApi = function(obj, action, name, rest) {
+ if (!name) return true;
+
+ // Handle event maps.
+ if (typeof name === 'object') {
+ for (var key in name) {
+ obj[action].apply(obj, [key, name[key]].concat(rest));
+ }
+ return false;
+ }
+
+ // Handle space separated event names.
+ if (eventSplitter.test(name)) {
+ var names = name.split(eventSplitter);
+ for (var i = 0, l = names.length; i < l; i++) {
+ obj[action].apply(obj, [names[i]].concat(rest));
+ }
+ return false;
+ }
+
+ return true;
+ };
+
+ // A difficult-to-believe, but optimized internal dispatch function for
+ // triggering events. Tries to keep the usual cases speedy (most internal
+ // Backbone events have 3 arguments).
+ var triggerEvents = function(events, args) {
+ var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
+ switch (args.length) {
+ case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
+ case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
+ case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
+ case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
+ default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
+ }
+ };
+
+ var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
+
+ // Inversion-of-control versions of `on` and `once`. Tell *this* object to
+ // listen to an event in another object ... keeping track of what it's
+ // listening to.
+ _.each(listenMethods, function(implementation, method) {
+ Events[method] = function(obj, name, callback) {
+ var listeningTo = this._listeningTo || (this._listeningTo = {});
+ var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
+ listeningTo[id] = obj;
+ if (!callback && typeof name === 'object') callback = this;
+ obj[implementation](name, callback, this);
+ return this;
+ };
+ });
+
+ // Aliases for backwards compatibility.
+ Events.bind = Events.on;
+ Events.unbind = Events.off;
+
+ // Allow the `Backbone` object to serve as a global event bus, for folks who
+ // want global "pubsub" in a convenient place.
+ _.extend(Backbone, Events);
+
+ // Backbone.Model
+ // --------------
+
+ // Backbone **Models** are the basic data object in the framework --
+ // frequently representing a row in a table in a database on your server.
+ // A discrete chunk of data and a bunch of useful, related methods for
+ // performing computations and transformations on that data.
+
+ // Create a new model with the specified attributes. A client id (`cid`)
+ // is automatically generated and assigned for you.
+ var Model = Backbone.Model = function(attributes, options) {
+ var attrs = attributes || {};
+ options || (options = {});
+ this.cid = _.uniqueId('c');
+ this.attributes = {};
+ if (options.collection) this.collection = options.collection;
+ if (options.parse) attrs = this.parse(attrs, options) || {};
+ attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
+ this.set(attrs, options);
+ this.changed = {};
+ this.initialize.apply(this, arguments);
+ };
+
+ // Attach all inheritable methods to the Model prototype.
+ _.extend(Model.prototype, Events, {
+
+ // A hash of attributes whose current and previous value differ.
+ changed: null,
+
+ // The value returned during the last failed validation.
+ validationError: null,
+
+ // The default name for the JSON `id` attribute is `"id"`. MongoDB and
+ // CouchDB users may want to set this to `"_id"`.
+ idAttribute: 'id',
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Return a copy of the model's `attributes` object.
+ toJSON: function(options) {
+ return _.clone(this.attributes);
+ },
+
+ // Proxy `Backbone.sync` by default -- but override this if you need
+ // custom syncing semantics for *this* particular model.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Get the value of an attribute.
+ get: function(attr) {
+ return this.attributes[attr];
+ },
+
+ // Get the HTML-escaped value of an attribute.
+ escape: function(attr) {
+ return _.escape(this.get(attr));
+ },
+
+ // Returns `true` if the attribute contains a value that is not null
+ // or undefined.
+ has: function(attr) {
+ return this.get(attr) != null;
+ },
+
+ // Set a hash of model attributes on the object, firing `"change"`. This is
+ // the core primitive operation of a model, updating the data and notifying
+ // anyone who needs to know about the change in state. The heart of the beast.
+ set: function(key, val, options) {
+ var attr, attrs, unset, changes, silent, changing, prev, current;
+ if (key == null) return this;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ if (typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options || (options = {});
+
+ // Run validation.
+ if (!this._validate(attrs, options)) return false;
+
+ // Extract attributes and options.
+ unset = options.unset;
+ silent = options.silent;
+ changes = [];
+ changing = this._changing;
+ this._changing = true;
+
+ if (!changing) {
+ this._previousAttributes = _.clone(this.attributes);
+ this.changed = {};
+ }
+ current = this.attributes, prev = this._previousAttributes;
+
+ // Check for changes of `id`.
+ if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
+
+ // For each `set` attribute, update or delete the current value.
+ for (attr in attrs) {
+ val = attrs[attr];
+ if (!_.isEqual(current[attr], val)) changes.push(attr);
+ if (!_.isEqual(prev[attr], val)) {
+ this.changed[attr] = val;
+ } else {
+ delete this.changed[attr];
+ }
+ unset ? delete current[attr] : current[attr] = val;
+ }
+
+ // Trigger all relevant attribute changes.
+ if (!silent) {
+ if (changes.length) this._pending = options;
+ for (var i = 0, l = changes.length; i < l; i++) {
+ this.trigger('change:' + changes[i], this, current[changes[i]], options);
+ }
+ }
+
+ // You might be wondering why there's a `while` loop here. Changes can
+ // be recursively nested within `"change"` events.
+ if (changing) return this;
+ if (!silent) {
+ while (this._pending) {
+ options = this._pending;
+ this._pending = false;
+ this.trigger('change', this, options);
+ }
+ }
+ this._pending = false;
+ this._changing = false;
+ return this;
+ },
+
+ // Remove an attribute from the model, firing `"change"`. `unset` is a noop
+ // if the attribute doesn't exist.
+ unset: function(attr, options) {
+ return this.set(attr, void 0, _.extend({}, options, {unset: true}));
+ },
+
+ // Clear all attributes on the model, firing `"change"`.
+ clear: function(options) {
+ var attrs = {};
+ for (var key in this.attributes) attrs[key] = void 0;
+ return this.set(attrs, _.extend({}, options, {unset: true}));
+ },
+
+ // Determine if the model has changed since the last `"change"` event.
+ // If you specify an attribute name, determine if that attribute has changed.
+ hasChanged: function(attr) {
+ if (attr == null) return !_.isEmpty(this.changed);
+ return _.has(this.changed, attr);
+ },
+
+ // Return an object containing all the attributes that have changed, or
+ // false if there are no changed attributes. Useful for determining what
+ // parts of a view need to be updated and/or what attributes need to be
+ // persisted to the server. Unset attributes will be set to undefined.
+ // You can also pass an attributes object to diff against the model,
+ // determining if there *would be* a change.
+ changedAttributes: function(diff) {
+ if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
+ var val, changed = false;
+ var old = this._changing ? this._previousAttributes : this.attributes;
+ for (var attr in diff) {
+ if (_.isEqual(old[attr], (val = diff[attr]))) continue;
+ (changed || (changed = {}))[attr] = val;
+ }
+ return changed;
+ },
+
+ // Get the previous value of an attribute, recorded at the time the last
+ // `"change"` event was fired.
+ previous: function(attr) {
+ if (attr == null || !this._previousAttributes) return null;
+ return this._previousAttributes[attr];
+ },
+
+ // Get all of the attributes of the model at the time of the previous
+ // `"change"` event.
+ previousAttributes: function() {
+ return _.clone(this._previousAttributes);
+ },
+
+ // Fetch the model from the server. If the server's representation of the
+ // model differs from its current attributes, they will be overridden,
+ // triggering a `"change"` event.
+ fetch: function(options) {
+ options = options ? _.clone(options) : {};
+ if (options.parse === void 0) options.parse = true;
+ var model = this;
+ var success = options.success;
+ options.success = function(resp) {
+ if (!model.set(model.parse(resp, options), options)) return false;
+ if (success) success(model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Set a hash of model attributes, and sync the model to the server.
+ // If the server returns an attributes hash that differs, the model's
+ // state will be `set` again.
+ save: function(key, val, options) {
+ var attrs, method, xhr, attributes = this.attributes;
+
+ // Handle both `"key", value` and `{key: value}` -style arguments.
+ if (key == null || typeof key === 'object') {
+ attrs = key;
+ options = val;
+ } else {
+ (attrs = {})[key] = val;
+ }
+
+ options = _.extend({validate: true}, options);
+
+ // If we're not waiting and attributes exist, save acts as
+ // `set(attr).save(null, opts)` with validation. Otherwise, check if
+ // the model will be valid when the attributes, if any, are set.
+ if (attrs && !options.wait) {
+ if (!this.set(attrs, options)) return false;
+ } else {
+ if (!this._validate(attrs, options)) return false;
+ }
+
+ // Set temporary attributes if `{wait: true}`.
+ if (attrs && options.wait) {
+ this.attributes = _.extend({}, attributes, attrs);
+ }
+
+ // After a successful server-side save, the client is (optionally)
+ // updated with the server-side state.
+ if (options.parse === void 0) options.parse = true;
+ var model = this;
+ var success = options.success;
+ options.success = function(resp) {
+ // Ensure attributes are restored during synchronous saves.
+ model.attributes = attributes;
+ var serverAttrs = model.parse(resp, options);
+ if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
+ if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
+ return false;
+ }
+ if (success) success(model, resp, options);
+ model.trigger('sync', model, resp, options);
+ };
+ wrapError(this, options);
+
+ method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
+ if (method === 'patch') options.attrs = attrs;
+ xhr = this.sync(method, this, options);
+
+ // Restore attributes.
+ if (attrs && options.wait) this.attributes = attributes;
+
+ return xhr;
+ },
+
+ // Destroy this model on the server if it was already persisted.
+ // Optimistically removes the model from its collection, if it has one.
+ // If `wait: true` is passed, waits for the server to respond before removal.
+ destroy: function(options) {
+ options = options ? _.clone(options) : {};
+ var model = this;
+ var success = options.success;
+
+ var destroy = function() {
+ model.trigger('destroy', model, model.collection, options);
+ };
+
+ options.success = function(resp) {
+ if (options.wait || model.isNew()) destroy();
+ if (success) success(model, resp, options);
+ if (!model.isNew()) model.trigger('sync', model, resp, options);
+ };
+
+ if (this.isNew()) {
+ options.success();
+ return false;
+ }
+ wrapError(this, options);
+
+ var xhr = this.sync('delete', this, options);
+ if (!options.wait) destroy();
+ return xhr;
+ },
+
+ // Default URL for the model's representation on the server -- if you're
+ // using Backbone's restful methods, override this to change the endpoint
+ // that will be called.
+ url: function() {
+ var base =
+ _.result(this, 'urlRoot') ||
+ _.result(this.collection, 'url') ||
+ urlError();
+ if (this.isNew()) return base;
+ return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
+ },
+
+ // **parse** converts a response into the hash of attributes to be `set` on
+ // the model. The default implementation is just to pass the response along.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new model with identical attributes to this one.
+ clone: function() {
+ return new this.constructor(this.attributes);
+ },
+
+ // A model is new if it has never been saved to the server, and lacks an id.
+ isNew: function() {
+ return !this.has(this.idAttribute);
+ },
+
+ // Check if the model is currently in a valid state.
+ isValid: function(options) {
+ return this._validate({}, _.extend(options || {}, { validate: true }));
+ },
+
+ // Run validation against the next complete set of model attributes,
+ // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
+ _validate: function(attrs, options) {
+ if (!options.validate || !this.validate) return true;
+ attrs = _.extend({}, this.attributes, attrs);
+ var error = this.validationError = this.validate(attrs, options) || null;
+ if (!error) return true;
+ this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
+ return false;
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Model.
+ var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit'];
+
+ // Mix in each Underscore method as a proxy to `Model#attributes`.
+ _.each(modelMethods, function(method) {
+ Model.prototype[method] = function() {
+ var args = slice.call(arguments);
+ args.unshift(this.attributes);
+ return _[method].apply(_, args);
+ };
+ });
+
+ // Backbone.Collection
+ // -------------------
+
+ // If models tend to represent a single row of data, a Backbone Collection is
+ // more analagous to a table full of data ... or a small slice or page of that
+ // table, or a collection of rows that belong together for a particular reason
+ // -- all of the messages in this particular folder, all of the documents
+ // belonging to this particular author, and so on. Collections maintain
+ // indexes of their models, both in order, and for lookup by `id`.
+
+ // Create a new **Collection**, perhaps to contain a specific type of `model`.
+ // If a `comparator` is specified, the Collection will maintain
+ // its models in sort order, as they're added and removed.
+ var Collection = Backbone.Collection = function(models, options) {
+ options || (options = {});
+ if (options.model) this.model = options.model;
+ if (options.comparator !== void 0) this.comparator = options.comparator;
+ this._reset();
+ this.initialize.apply(this, arguments);
+ if (models) this.reset(models, _.extend({silent: true}, options));
+ };
+
+ // Default options for `Collection#set`.
+ var setOptions = {add: true, remove: true, merge: true};
+ var addOptions = {add: true, remove: false};
+
+ // Define the Collection's inheritable methods.
+ _.extend(Collection.prototype, Events, {
+
+ // The default model for a collection is just a **Backbone.Model**.
+ // This should be overridden in most cases.
+ model: Model,
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // The JSON representation of a Collection is an array of the
+ // models' attributes.
+ toJSON: function(options) {
+ return this.map(function(model){ return model.toJSON(options); });
+ },
+
+ // Proxy `Backbone.sync` by default.
+ sync: function() {
+ return Backbone.sync.apply(this, arguments);
+ },
+
+ // Add a model, or list of models to the set.
+ add: function(models, options) {
+ return this.set(models, _.extend({merge: false}, options, addOptions));
+ },
+
+ // Remove a model, or a list of models from the set.
+ remove: function(models, options) {
+ var singular = !_.isArray(models);
+ models = singular ? [models] : _.clone(models);
+ options || (options = {});
+ var i, l, index, model;
+ for (i = 0, l = models.length; i < l; i++) {
+ model = models[i] = this.get(models[i]);
+ if (!model) continue;
+ delete this._byId[model.id];
+ delete this._byId[model.cid];
+ index = this.indexOf(model);
+ this.models.splice(index, 1);
+ this.length--;
+ if (!options.silent) {
+ options.index = index;
+ model.trigger('remove', model, this, options);
+ }
+ this._removeReference(model, options);
+ }
+ return singular ? models[0] : models;
+ },
+
+ // Update a collection by `set`-ing a new list of models, adding new ones,
+ // removing models that are no longer present, and merging models that
+ // already exist in the collection, as necessary. Similar to **Model#set**,
+ // the core operation for updating the data contained by the collection.
+ set: function(models, options) {
+ options = _.defaults({}, options, setOptions);
+ if (options.parse) models = this.parse(models, options);
+ var singular = !_.isArray(models);
+ models = singular ? (models ? [models] : []) : _.clone(models);
+ var i, l, id, model, attrs, existing, sort;
+ var at = options.at;
+ var targetModel = this.model;
+ var sortable = this.comparator && (at == null) && options.sort !== false;
+ var sortAttr = _.isString(this.comparator) ? this.comparator : null;
+ var toAdd = [], toRemove = [], modelMap = {};
+ var add = options.add, merge = options.merge, remove = options.remove;
+ var order = !sortable && add && remove ? [] : false;
+
+ // Turn bare objects into model references, and prevent invalid models
+ // from being added.
+ for (i = 0, l = models.length; i < l; i++) {
+ attrs = models[i] || {};
+ if (attrs instanceof Model) {
+ id = model = attrs;
+ } else {
+ id = attrs[targetModel.prototype.idAttribute || 'id'];
+ }
+
+ // If a duplicate is found, prevent it from being added and
+ // optionally merge it into the existing model.
+ if (existing = this.get(id)) {
+ if (remove) modelMap[existing.cid] = true;
+ if (merge) {
+ attrs = attrs === model ? model.attributes : attrs;
+ if (options.parse) attrs = existing.parse(attrs, options);
+ existing.set(attrs, options);
+ if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
+ }
+ models[i] = existing;
+
+ // If this is a new, valid model, push it to the `toAdd` list.
+ } else if (add) {
+ model = models[i] = this._prepareModel(attrs, options);
+ if (!model) continue;
+ toAdd.push(model);
+ this._addReference(model, options);
+ }
+
+ // Do not add multiple models with the same `id`.
+ model = existing || model;
+ if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
+ modelMap[model.id] = true;
+ }
+
+ // Remove nonexistent models if appropriate.
+ if (remove) {
+ for (i = 0, l = this.length; i < l; ++i) {
+ if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
+ }
+ if (toRemove.length) this.remove(toRemove, options);
+ }
+
+ // See if sorting is needed, update `length` and splice in new models.
+ if (toAdd.length || (order && order.length)) {
+ if (sortable) sort = true;
+ this.length += toAdd.length;
+ if (at != null) {
+ for (i = 0, l = toAdd.length; i < l; i++) {
+ this.models.splice(at + i, 0, toAdd[i]);
+ }
+ } else {
+ if (order) this.models.length = 0;
+ var orderedModels = order || toAdd;
+ for (i = 0, l = orderedModels.length; i < l; i++) {
+ this.models.push(orderedModels[i]);
+ }
+ }
+ }
+
+ // Silently sort the collection if appropriate.
+ if (sort) this.sort({silent: true});
+
+ // Unless silenced, it's time to fire all appropriate add/sort events.
+ if (!options.silent) {
+ for (i = 0, l = toAdd.length; i < l; i++) {
+ (model = toAdd[i]).trigger('add', model, this, options);
+ }
+ if (sort || (order && order.length)) this.trigger('sort', this, options);
+ }
+
+ // Return the added (or merged) model (or models).
+ return singular ? models[0] : models;
+ },
+
+ // When you have more items than you want to add or remove individually,
+ // you can reset the entire set with a new list of models, without firing
+ // any granular `add` or `remove` events. Fires `reset` when finished.
+ // Useful for bulk operations and optimizations.
+ reset: function(models, options) {
+ options || (options = {});
+ for (var i = 0, l = this.models.length; i < l; i++) {
+ this._removeReference(this.models[i], options);
+ }
+ options.previousModels = this.models;
+ this._reset();
+ models = this.add(models, _.extend({silent: true}, options));
+ if (!options.silent) this.trigger('reset', this, options);
+ return models;
+ },
+
+ // Add a model to the end of the collection.
+ push: function(model, options) {
+ return this.add(model, _.extend({at: this.length}, options));
+ },
+
+ // Remove a model from the end of the collection.
+ pop: function(options) {
+ var model = this.at(this.length - 1);
+ this.remove(model, options);
+ return model;
+ },
+
+ // Add a model to the beginning of the collection.
+ unshift: function(model, options) {
+ return this.add(model, _.extend({at: 0}, options));
+ },
+
+ // Remove a model from the beginning of the collection.
+ shift: function(options) {
+ var model = this.at(0);
+ this.remove(model, options);
+ return model;
+ },
+
+ // Slice out a sub-array of models from the collection.
+ slice: function() {
+ return slice.apply(this.models, arguments);
+ },
+
+ // Get a model from the set by id.
+ get: function(obj) {
+ if (obj == null) return void 0;
+ return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
+ },
+
+ // Get the model at the given index.
+ at: function(index) {
+ return this.models[index];
+ },
+
+ // Return models with matching attributes. Useful for simple cases of
+ // `filter`.
+ where: function(attrs, first) {
+ if (_.isEmpty(attrs)) return first ? void 0 : [];
+ return this[first ? 'find' : 'filter'](function(model) {
+ for (var key in attrs) {
+ if (attrs[key] !== model.get(key)) return false;
+ }
+ return true;
+ });
+ },
+
+ // Return the first model with matching attributes. Useful for simple cases
+ // of `find`.
+ findWhere: function(attrs) {
+ return this.where(attrs, true);
+ },
+
+ // Force the collection to re-sort itself. You don't need to call this under
+ // normal circumstances, as the set will maintain sort order as each item
+ // is added.
+ sort: function(options) {
+ if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
+ options || (options = {});
+
+ // Run sort based on type of `comparator`.
+ if (_.isString(this.comparator) || this.comparator.length === 1) {
+ this.models = this.sortBy(this.comparator, this);
+ } else {
+ this.models.sort(_.bind(this.comparator, this));
+ }
+
+ if (!options.silent) this.trigger('sort', this, options);
+ return this;
+ },
+
+ // Pluck an attribute from each model in the collection.
+ pluck: function(attr) {
+ return _.invoke(this.models, 'get', attr);
+ },
+
+ // Fetch the default set of models for this collection, resetting the
+ // collection when they arrive. If `reset: true` is passed, the response
+ // data will be passed through the `reset` method instead of `set`.
+ fetch: function(options) {
+ options = options ? _.clone(options) : {};
+ if (options.parse === void 0) options.parse = true;
+ var success = options.success;
+ var collection = this;
+ options.success = function(resp) {
+ var method = options.reset ? 'reset' : 'set';
+ collection[method](resp, options);
+ if (success) success(collection, resp, options);
+ collection.trigger('sync', collection, resp, options);
+ };
+ wrapError(this, options);
+ return this.sync('read', this, options);
+ },
+
+ // Create a new instance of a model in this collection. Add the model to the
+ // collection immediately, unless `wait: true` is passed, in which case we
+ // wait for the server to agree.
+ create: function(model, options) {
+ options = options ? _.clone(options) : {};
+ if (!(model = this._prepareModel(model, options))) return false;
+ if (!options.wait) this.add(model, options);
+ var collection = this;
+ var success = options.success;
+ options.success = function(model, resp) {
+ if (options.wait) collection.add(model, options);
+ if (success) success(model, resp, options);
+ };
+ model.save(null, options);
+ return model;
+ },
+
+ // **parse** converts a response into a list of models to be added to the
+ // collection. The default implementation is just to pass it through.
+ parse: function(resp, options) {
+ return resp;
+ },
+
+ // Create a new collection with an identical list of models as this one.
+ clone: function() {
+ return new this.constructor(this.models);
+ },
+
+ // Private method to reset all internal state. Called when the collection
+ // is first initialized or reset.
+ _reset: function() {
+ this.length = 0;
+ this.models = [];
+ this._byId = {};
+ },
+
+ // Prepare a hash of attributes (or other model) to be added to this
+ // collection.
+ _prepareModel: function(attrs, options) {
+ if (attrs instanceof Model) return attrs;
+ options = options ? _.clone(options) : {};
+ options.collection = this;
+ var model = new this.model(attrs, options);
+ if (!model.validationError) return model;
+ this.trigger('invalid', this, model.validationError, options);
+ return false;
+ },
+
+ // Internal method to create a model's ties to a collection.
+ _addReference: function(model, options) {
+ this._byId[model.cid] = model;
+ if (model.id != null) this._byId[model.id] = model;
+ if (!model.collection) model.collection = this;
+ model.on('all', this._onModelEvent, this);
+ },
+
+ // Internal method to sever a model's ties to a collection.
+ _removeReference: function(model, options) {
+ if (this === model.collection) delete model.collection;
+ model.off('all', this._onModelEvent, this);
+ },
+
+ // Internal method called every time a model in the set fires an event.
+ // Sets need to update their indexes when models change ids. All other
+ // events simply proxy through. "add" and "remove" events that originate
+ // in other collections are ignored.
+ _onModelEvent: function(event, model, collection, options) {
+ if ((event === 'add' || event === 'remove') && collection !== this) return;
+ if (event === 'destroy') this.remove(model, options);
+ if (model && event === 'change:' + model.idAttribute) {
+ delete this._byId[model.previous(model.idAttribute)];
+ if (model.id != null) this._byId[model.id] = model;
+ }
+ this.trigger.apply(this, arguments);
+ }
+
+ });
+
+ // Underscore methods that we want to implement on the Collection.
+ // 90% of the core usefulness of Backbone Collections is actually implemented
+ // right here:
+ var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
+ 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
+ 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
+ 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
+ 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
+ 'lastIndexOf', 'isEmpty', 'chain', 'sample'];
+
+ // Mix in each Underscore method as a proxy to `Collection#models`.
+ _.each(methods, function(method) {
+ Collection.prototype[method] = function() {
+ var args = slice.call(arguments);
+ args.unshift(this.models);
+ return _[method].apply(_, args);
+ };
+ });
+
+ // Underscore methods that take a property name as an argument.
+ var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
+
+ // Use attributes instead of properties.
+ _.each(attributeMethods, function(method) {
+ Collection.prototype[method] = function(value, context) {
+ var iterator = _.isFunction(value) ? value : function(model) {
+ return model.get(value);
+ };
+ return _[method](this.models, iterator, context);
+ };
+ });
+
+ // Backbone.View
+ // -------------
+
+ // Backbone Views are almost more convention than they are actual code. A View
+ // is simply a JavaScript object that represents a logical chunk of UI in the
+ // DOM. This might be a single item, an entire list, a sidebar or panel, or
+ // even the surrounding frame which wraps your whole app. Defining a chunk of
+ // UI as a **View** allows you to define your DOM events declaratively, without
+ // having to worry about render order ... and makes it easy for the view to
+ // react to specific changes in the state of your models.
+
+ // Creating a Backbone.View creates its initial element outside of the DOM,
+ // if an existing element is not provided...
+ var View = Backbone.View = function(options) {
+ this.cid = _.uniqueId('view');
+ options || (options = {});
+ _.extend(this, _.pick(options, viewOptions));
+ this._ensureElement();
+ this.initialize.apply(this, arguments);
+ this.delegateEvents();
+ };
+
+ // Cached regex to split keys for `delegate`.
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+
+ // List of view options to be merged as properties.
+ var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
+
+ // Set up all inheritable **Backbone.View** properties and methods.
+ _.extend(View.prototype, Events, {
+
+ // The default `tagName` of a View's element is `"div"`.
+ tagName: 'div',
+
+ // jQuery delegate for element lookup, scoped to DOM elements within the
+ // current view. This should be preferred to global lookups where possible.
+ $: function(selector) {
+ return this.$el.find(selector);
+ },
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // **render** is the core function that your view should override, in order
+ // to populate its element (`this.el`), with the appropriate HTML. The
+ // convention is for **render** to always return `this`.
+ render: function() {
+ return this;
+ },
+
+ // Remove this view by taking the element out of the DOM, and removing any
+ // applicable Backbone.Events listeners.
+ remove: function() {
+ this.$el.remove();
+ this.stopListening();
+ return this;
+ },
+
+ // Change the view's element (`this.el` property), including event
+ // re-delegation.
+ setElement: function(element, delegate) {
+ if (this.$el) this.undelegateEvents();
+ this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
+ this.el = this.$el[0];
+ if (delegate !== false) this.delegateEvents();
+ return this;
+ },
+
+ // Set callbacks, where `this.events` is a hash of
+ //
+ // *{"event selector": "callback"}*
+ //
+ // {
+ // 'mousedown .title': 'edit',
+ // 'click .button': 'save',
+ // 'click .open': function(e) { ... }
+ // }
+ //
+ // pairs. Callbacks will be bound to the view, with `this` set properly.
+ // Uses event delegation for efficiency.
+ // Omitting the selector binds the event to `this.el`.
+ // This only works for delegate-able events: not `focus`, `blur`, and
+ // not `change`, `submit`, and `reset` in Internet Explorer.
+ delegateEvents: function(events) {
+ if (!(events || (events = _.result(this, 'events')))) return this;
+ this.undelegateEvents();
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[events[key]];
+ if (!method) continue;
+
+ var match = key.match(delegateEventSplitter);
+ var eventName = match[1], selector = match[2];
+ method = _.bind(method, this);
+ eventName += '.delegateEvents' + this.cid;
+ if (selector === '') {
+ this.$el.on(eventName, method);
+ } else {
+ this.$el.on(eventName, selector, method);
+ }
+ }
+ return this;
+ },
+
+ // Clears all callbacks previously bound to the view with `delegateEvents`.
+ // You usually don't need to use this, but may wish to if you have multiple
+ // Backbone views attached to the same DOM element.
+ undelegateEvents: function() {
+ this.$el.off('.delegateEvents' + this.cid);
+ return this;
+ },
+
+ // Ensure that the View has a DOM element to render into.
+ // If `this.el` is a string, pass it through `$()`, take the first
+ // matching element, and re-assign it to `el`. Otherwise, create
+ // an element from the `id`, `className` and `tagName` properties.
+ _ensureElement: function() {
+ if (!this.el) {
+ var attrs = _.extend({}, _.result(this, 'attributes'));
+ if (this.id) attrs.id = _.result(this, 'id');
+ if (this.className) attrs['class'] = _.result(this, 'className');
+ var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);
+ this.setElement($el, false);
+ } else {
+ this.setElement(_.result(this, 'el'), false);
+ }
+ }
+
+ });
+
+ // Backbone.sync
+ // -------------
+
+ // Override this function to change the manner in which Backbone persists
+ // models to the server. You will be passed the type of request, and the
+ // model in question. By default, makes a RESTful Ajax request
+ // to the model's `url()`. Some possible customizations could be:
+ //
+ // * Use `setTimeout` to batch rapid-fire updates into a single request.
+ // * Send up the models as XML instead of JSON.
+ // * Persist models via WebSockets instead of Ajax.
+ //
+ // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
+ // as `POST`, with a `_method` parameter containing the true HTTP method,
+ // as well as all requests with the body as `application/x-www-form-urlencoded`
+ // instead of `application/json` with the model in a param named `model`.
+ // Useful when interfacing with server-side languages like **PHP** that make
+ // it difficult to read the body of `PUT` requests.
+ Backbone.sync = function(method, model, options) {
+ var type = methodMap[method];
+
+ // Default options, unless specified.
+ _.defaults(options || (options = {}), {
+ emulateHTTP: Backbone.emulateHTTP,
+ emulateJSON: Backbone.emulateJSON
+ });
+
+ // Default JSON-request options.
+ var params = {type: type, dataType: 'json'};
+
+ // Ensure that we have a URL.
+ if (!options.url) {
+ params.url = _.result(model, 'url') || urlError();
+ }
+
+ // Ensure that we have the appropriate request data.
+ if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
+ params.contentType = 'application/json';
+ params.data = JSON.stringify(options.attrs || model.toJSON(options));
+ }
+
+ // For older servers, emulate JSON by encoding the request into an HTML-form.
+ if (options.emulateJSON) {
+ params.contentType = 'application/x-www-form-urlencoded';
+ params.data = params.data ? {model: params.data} : {};
+ }
+
+ // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
+ // And an `X-HTTP-Method-Override` header.
+ if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
+ params.type = 'POST';
+ if (options.emulateJSON) params.data._method = type;
+ var beforeSend = options.beforeSend;
+ options.beforeSend = function(xhr) {
+ xhr.setRequestHeader('X-HTTP-Method-Override', type);
+ if (beforeSend) return beforeSend.apply(this, arguments);
+ };
+ }
+
+ // Don't process data on a non-GET request.
+ if (params.type !== 'GET' && !options.emulateJSON) {
+ params.processData = false;
+ }
+
+ // If we're sending a `PATCH` request, and we're in an old Internet Explorer
+ // that still has ActiveX enabled by default, override jQuery to use that
+ // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
+ if (params.type === 'PATCH' && noXhrPatch) {
+ params.xhr = function() {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ };
+ }
+
+ // Make the request, allowing the user to override any Ajax options.
+ var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
+ model.trigger('request', model, xhr, options);
+ return xhr;
+ };
+
+ var noXhrPatch =
+ typeof window !== 'undefined' && !!window.ActiveXObject &&
+ !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
+
+ // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
+ var methodMap = {
+ 'create': 'POST',
+ 'update': 'PUT',
+ 'patch': 'PATCH',
+ 'delete': 'DELETE',
+ 'read': 'GET'
+ };
+
+ // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
+ // Override this if you'd like to use a different library.
+ Backbone.ajax = function() {
+ return Backbone.$.ajax.apply(Backbone.$, arguments);
+ };
+
+ // Backbone.Router
+ // ---------------
+
+ // Routers map faux-URLs to actions, and fire events when routes are
+ // matched. Creating a new one sets its `routes` hash, if not set statically.
+ var Router = Backbone.Router = function(options) {
+ options || (options = {});
+ if (options.routes) this.routes = options.routes;
+ this._bindRoutes();
+ this.initialize.apply(this, arguments);
+ };
+
+ // Cached regular expressions for matching named param parts and splatted
+ // parts of route strings.
+ var optionalParam = /\((.*?)\)/g;
+ var namedParam = /(\(\?)?:\w+/g;
+ var splatParam = /\*\w+/g;
+ var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
+
+ // Set up all inheritable **Backbone.Router** properties and methods.
+ _.extend(Router.prototype, Events, {
+
+ // Initialize is an empty function by default. Override it with your own
+ // initialization logic.
+ initialize: function(){},
+
+ // Manually bind a single named route to a callback. For example:
+ //
+ // this.route('search/:query/p:num', 'search', function(query, num) {
+ // ...
+ // });
+ //
+ route: function(route, name, callback) {
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ if (_.isFunction(name)) {
+ callback = name;
+ name = '';
+ }
+ if (!callback) callback = this[name];
+ var router = this;
+ Backbone.history.route(route, function(fragment) {
+ var args = router._extractParameters(route, fragment);
+ router.execute(callback, args);
+ router.trigger.apply(router, ['route:' + name].concat(args));
+ router.trigger('route', name, args);
+ Backbone.history.trigger('route', router, name, args);
+ });
+ return this;
+ },
+
+ // Execute a route handler with the provided parameters. This is an
+ // excellent place to do pre-route setup or post-route cleanup.
+ execute: function(callback, args) {
+ if (callback) callback.apply(this, args);
+ },
+
+ // Simple proxy to `Backbone.history` to save a fragment into the history.
+ navigate: function(fragment, options) {
+ Backbone.history.navigate(fragment, options);
+ return this;
+ },
+
+ // Bind all defined routes to `Backbone.history`. We have to reverse the
+ // order of the routes here to support behavior where the most general
+ // routes can be defined at the bottom of the route map.
+ _bindRoutes: function() {
+ if (!this.routes) return;
+ this.routes = _.result(this, 'routes');
+ var route, routes = _.keys(this.routes);
+ while ((route = routes.pop()) != null) {
+ this.route(route, this.routes[route]);
+ }
+ },
+
+ // Convert a route string into a regular expression, suitable for matching
+ // against the current location hash.
+ _routeToRegExp: function(route) {
+ route = route.replace(escapeRegExp, '\\$&')
+ .replace(optionalParam, '(?:$1)?')
+ .replace(namedParam, function(match, optional) {
+ return optional ? match : '([^/?]+)';
+ })
+ .replace(splatParam, '([^?]*?)');
+ return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
+ },
+
+ // Given a route, and a URL fragment that it matches, return the array of
+ // extracted decoded parameters. Empty or unmatched parameters will be
+ // treated as `null` to normalize cross-browser behavior.
+ _extractParameters: function(route, fragment) {
+ var params = route.exec(fragment).slice(1);
+ return _.map(params, function(param, i) {
+ // Don't decode the search params.
+ if (i === params.length - 1) return param || null;
+ return param ? decodeURIComponent(param) : null;
+ });
+ }
+
+ });
+
+ // Backbone.History
+ // ----------------
+
+ // Handles cross-browser history management, based on either
+ // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
+ // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
+ // and URL fragments. If the browser supports neither (old IE, natch),
+ // falls back to polling.
+ var History = Backbone.History = function() {
+ this.handlers = [];
+ _.bindAll(this, 'checkUrl');
+
+ // Ensure that `History` can be used outside of the browser.
+ if (typeof window !== 'undefined') {
+ this.location = window.location;
+ this.history = window.history;
+ }
+ };
+
+ // Cached regex for stripping a leading hash/slash and trailing space.
+ var routeStripper = /^[#\/]|\s+$/g;
+
+ // Cached regex for stripping leading and trailing slashes.
+ var rootStripper = /^\/+|\/+$/g;
+
+ // Cached regex for detecting MSIE.
+ var isExplorer = /msie [\w.]+/;
+
+ // Cached regex for removing a trailing slash.
+ var trailingSlash = /\/$/;
+
+ // Cached regex for stripping urls of hash.
+ var pathStripper = /#.*$/;
+
+ // Has the history handling already been started?
+ History.started = false;
+
+ // Set up all inheritable **Backbone.History** properties and methods.
+ _.extend(History.prototype, Events, {
+
+ // The default interval to poll for hash changes, if necessary, is
+ // twenty times a second.
+ interval: 50,
+
+ // Are we at the app root?
+ atRoot: function() {
+ return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root;
+ },
+
+ // Gets the true hash value. Cannot use location.hash directly due to bug
+ // in Firefox where location.hash will always be decoded.
+ getHash: function(window) {
+ var match = (window || this).location.href.match(/#(.*)$/);
+ return match ? match[1] : '';
+ },
+
+ // Get the cross-browser normalized URL fragment, either from the URL,
+ // the hash, or the override.
+ getFragment: function(fragment, forcePushState) {
+ if (fragment == null) {
+ if (this._hasPushState || !this._wantsHashChange || forcePushState) {
+ fragment = decodeURI(this.location.pathname + this.location.search);
+ var root = this.root.replace(trailingSlash, '');
+ if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
+ } else {
+ fragment = this.getHash();
+ }
+ }
+ return fragment.replace(routeStripper, '');
+ },
+
+ // Start the hash change handling, returning `true` if the current URL matches
+ // an existing route, and `false` otherwise.
+ start: function(options) {
+ if (History.started) throw new Error("Backbone.history has already been started");
+ History.started = true;
+
+ // Figure out the initial configuration. Do we need an iframe?
+ // Is pushState desired ... is it available?
+ this.options = _.extend({root: '/'}, this.options, options);
+ this.root = this.options.root;
+ this._wantsHashChange = this.options.hashChange !== false;
+ this._wantsPushState = !!this.options.pushState;
+ this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
+ var fragment = this.getFragment();
+ var docMode = document.documentMode;
+ var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
+
+ // Normalize root to always include a leading and trailing slash.
+ this.root = ('/' + this.root + '/').replace(rootStripper, '/');
+
+ if (oldIE && this._wantsHashChange) {
+ var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
+ this.iframe = frame.hide().appendTo('body')[0].contentWindow;
+ this.navigate(fragment);
+ }
+
+ // Depending on whether we're using pushState or hashes, and whether
+ // 'onhashchange' is supported, determine how we check the URL state.
+ if (this._hasPushState) {
+ Backbone.$(window).on('popstate', this.checkUrl);
+ } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
+ Backbone.$(window).on('hashchange', this.checkUrl);
+ } else if (this._wantsHashChange) {
+ this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
+ }
+
+ // Determine if we need to change the base url, for a pushState link
+ // opened by a non-pushState browser.
+ this.fragment = fragment;
+ var loc = this.location;
+
+ // Transition from hashChange to pushState or vice versa if both are
+ // requested.
+ if (this._wantsHashChange && this._wantsPushState) {
+
+ // If we've started off with a route from a `pushState`-enabled
+ // browser, but we're currently in a browser that doesn't support it...
+ if (!this._hasPushState && !this.atRoot()) {
+ this.fragment = this.getFragment(null, true);
+ this.location.replace(this.root + '#' + this.fragment);
+ // Return immediately as browser will do redirect to new url
+ return true;
+
+ // Or if we've started out with a hash-based route, but we're currently
+ // in a browser where it could be `pushState`-based instead...
+ } else if (this._hasPushState && this.atRoot() && loc.hash) {
+ this.fragment = this.getHash().replace(routeStripper, '');
+ this.history.replaceState({}, document.title, this.root + this.fragment);
+ }
+
+ }
+
+ if (!this.options.silent) return this.loadUrl();
+ },
+
+ // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
+ // but possibly useful for unit testing Routers.
+ stop: function() {
+ Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
+ if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
+ History.started = false;
+ },
+
+ // Add a route to be tested when the fragment changes. Routes added later
+ // may override previous routes.
+ route: function(route, callback) {
+ this.handlers.unshift({route: route, callback: callback});
+ },
+
+ // Checks the current URL to see if it has changed, and if it has,
+ // calls `loadUrl`, normalizing across the hidden iframe.
+ checkUrl: function(e) {
+ var current = this.getFragment();
+ if (current === this.fragment && this.iframe) {
+ current = this.getFragment(this.getHash(this.iframe));
+ }
+ if (current === this.fragment) return false;
+ if (this.iframe) this.navigate(current);
+ this.loadUrl();
+ },
+
+ // Attempt to load the current URL fragment. If a route succeeds with a
+ // match, returns `true`. If no defined routes matches the fragment,
+ // returns `false`.
+ loadUrl: function(fragment) {
+ fragment = this.fragment = this.getFragment(fragment);
+ return _.any(this.handlers, function(handler) {
+ if (handler.route.test(fragment)) {
+ handler.callback(fragment);
+ return true;
+ }
+ });
+ },
+
+ // Save a fragment into the hash history, or replace the URL state if the
+ // 'replace' option is passed. You are responsible for properly URL-encoding
+ // the fragment in advance.
+ //
+ // The options object can contain `trigger: true` if you wish to have the
+ // route callback be fired (not usually desirable), or `replace: true`, if
+ // you wish to modify the current URL without adding an entry to the history.
+ navigate: function(fragment, options) {
+ if (!History.started) return false;
+ if (!options || options === true) options = {trigger: !!options};
+
+ var url = this.root + (fragment = this.getFragment(fragment || ''));
+
+ // Strip the hash for matching.
+ fragment = fragment.replace(pathStripper, '');
+
+ if (this.fragment === fragment) return;
+ this.fragment = fragment;
+
+ // Don't include a trailing slash on the root.
+ if (fragment === '' && url !== '/') url = url.slice(0, -1);
+
+ // If pushState is available, we use it to set the fragment as a real URL.
+ if (this._hasPushState) {
+ this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
+
+ // If hash changes haven't been explicitly disabled, update the hash
+ // fragment to store history.
+ } else if (this._wantsHashChange) {
+ this._updateHash(this.location, fragment, options.replace);
+ if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) {
+ // Opening and closing the iframe tricks IE7 and earlier to push a
+ // history entry on hash-tag change. When replace is true, we don't
+ // want this.
+ if(!options.replace) this.iframe.document.open().close();
+ this._updateHash(this.iframe.location, fragment, options.replace);
+ }
+
+ // If you've told us that you explicitly don't want fallback hashchange-
+ // based history, then `navigate` becomes a page refresh.
+ } else {
+ return this.location.assign(url);
+ }
+ if (options.trigger) return this.loadUrl(fragment);
+ },
+
+ // Update the hash location, either replacing the current entry, or adding
+ // a new one to the browser history.
+ _updateHash: function(location, fragment, replace) {
+ if (replace) {
+ var href = location.href.replace(/(javascript:|#).*$/, '');
+ location.replace(href + '#' + fragment);
+ } else {
+ // Some browsers require that `hash` contains a leading #.
+ location.hash = '#' + fragment;
+ }
+ }
+
+ });
+
+ // Create the default Backbone.history.
+ Backbone.history = new History;
+
+ // Helpers
+ // -------
+
+ // Helper function to correctly set up the prototype chain, for subclasses.
+ // Similar to `goog.inherits`, but uses a hash of prototype properties and
+ // class properties to be extended.
+ var extend = function(protoProps, staticProps) {
+ var parent = this;
+ var child;
+
+ // The constructor function for the new subclass is either defined by you
+ // (the "constructor" property in your `extend` definition), or defaulted
+ // by us to simply call the parent's constructor.
+ if (protoProps && _.has(protoProps, 'constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function(){ return parent.apply(this, arguments); };
+ }
+
+ // Add static properties to the constructor function, if supplied.
+ _.extend(child, parent, staticProps);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent`'s constructor function.
+ var Surrogate = function(){ this.constructor = child; };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps) _.extend(child.prototype, protoProps);
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ // Set up inheritance for the model, collection, router, view and history.
+ Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
+
+ // Throw an error when a URL is needed, and none is supplied.
+ var urlError = function() {
+ throw new Error('A "url" property or function must be specified');
+ };
+
+ // Wrap an optional error callback with a fallback error event.
+ var wrapError = function(model, options) {
+ var error = options.error;
+ options.error = function(resp) {
+ if (error) error(model, resp, options);
+ model.trigger('error', model, resp, options);
+ };
+ };
+
+ return Backbone;
+
+}));
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/css/backgrid-0.3.5.min.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/css/backgrid-0.3.5.min.css b/htrace-htraced/src/web/lib/css/backgrid-0.3.5.min.css
deleted file mode 100644
index 764e799..0000000
--- a/htrace-htraced/src/web/lib/css/backgrid-0.3.5.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.backgrid-container{position:relative;display:block;width:100%;height:465px;padding:0;overflow:auto;border:0}.backgrid{width:100%;max-width:100%;background-color:transparent;border-collapse:collapse;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.backgrid th,.backgrid td{display:none;height:20px;max-width:250px;padding:4px 5px;overflow:hidden;line-height:20px;text-align:left;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;border-bottom:1px solid #DDD}.backgrid th.renderable,.backgrid td.renderable{display:table-cell}.backgrid th{font-weight:bold;text-align:center}.backgrid th.sortable a{text-decoration:none;white-space:nowrap;cursor:pointer}.backgrid thead th{vertical-align:bottom;background-color:#f9f9f9}.backgrid thead th a{display:block}.backgrid.backgrid-striped tbody tr:nth-child(even){background-color:#f9f9f9}.backgrid tbody tr.empty{font-style:italic;color:gray}.backgrid tbody tr.empty td{display:inherit;text-align:center}.backgrid td.edito
r{padding:0}.backgrid td.editor,.backgrid tbody tr:nth-child(odd) td.editor{background-color:rgba(82,168,236,0.1);outline:1px solid rgba(82,168,236,0.8);outline-offset:-1px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition-duration:200ms;-moz-transition-duration:200ms;-o-transition-duration:200ms;transition-duration:200ms;-webkit-transition-property:width,outline,background-color;-moz-transition-property:width,outline,background-color;-o-transition-property:width,outline,background-color;transition-property:width,outline,background-color;-webkit-transition-timing-function:ease-in-out;-moz-transition-timing-function:ease-in-out;-o-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out}.backgrid td.editor input[type=text]{display:block;width:100%;height:100%;padding:0 5px;margin:0;background-color:transparent;border:0;outline:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;-webkit-box-sizing:border-b
ox;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none}.backgrid td.editor input[type=text]::-ms-clear{display:none}.backgrid td.error,.backgrid tbody tr:nth-child(odd) td.error{background-color:rgba(255,210,77,0.1);outline:1px solid #ffd24d}.backgrid td.editor :focus,.backgrid th.editor:focus{outline:0}.backgrid .sort-caret{display:inline-block;width:0;height:0;margin-left:.3em;border:0;content:""}.backgrid .ascending .sort-caret{vertical-align:baseline;border-top:0;border-right:4px solid transparent;border-bottom:4px solid #000;border-left:4px solid transparent}.backgrid .descending .sort-caret{vertical-align:super;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0;border-left:4px solid transparent}.backgrid .string-cell,.backgrid .uri-cell,.backgrid .email-cell,.backgrid .string-cell.editor input[type=text],.backgrid .uri-cell.editor input[type=text],.backgrid .email-cell.editor input[type=text]{text-align:left}.
backgrid .date-cell,.backgrid .time-cell,.backgrid .datetime-cell,.backgrid .number-cell,.backgrid .integer-cell,.backgrid .percent-cell,.backgrid .date-cell.editor input[type=text],.backgrid .time-cell.editor input[type=text],.backgrid .datetime-cell.editor input[type=text],.backgrid .number-cell.editor input[type=text],.backgrid .integer-cell.editor input[type=text],.backgrid .percent-cell.editor input[type=text]{text-align:right}.backgrid .boolean-cell,.backgrid .boolean-cell.editor input[type=checkbox]{text-align:center}.backgrid .select-cell{text-align:center}.backgrid .select-cell.editor{padding:0}.backgrid .select-cell.editor select{display:block;width:100%;height:28px;padding:4px 5px;margin:0;line-height:28px;vertical-align:middle;background-color:white;border:0;outline:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.backgrid .select-cell.editor select[multiple]{height:auto}.backgr
id .select-cell.editor :focus{border:0;outline:0}.backgrid .select-cell.editor select::-moz-focus-inner,.backgrid .select-cell.editor optgroup::-moz-focus-inner,.backgrid .select-cell.editor option::-moz-focus-inner,.backgrid .select-cell.editor select::-o-focus-inner,.backgrid .select-cell.editor optgroup::-o-focus-inner,.backgrid .select-cell.editor option::-o-focus-inner{border:0}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/css/backgrid-paginator-0.3.5.min.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/css/backgrid-paginator-0.3.5.min.css b/htrace-htraced/src/web/lib/css/backgrid-paginator-0.3.5.min.css
deleted file mode 100644
index 285fe81..0000000
--- a/htrace-htraced/src/web/lib/css/backgrid-paginator-0.3.5.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.backgrid-paginator{text-align:center;border-top:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.backgrid-paginator ul{display:inline-block;*display:inline;margin:5px 0;*zoom:1}.backgrid-paginator ul>li{display:inline}.backgrid-paginator ul>li>a,.backgrid-paginator ul>li>span{float:left;width:30px;height:30px;padding:0;line-height:30px;text-decoration:none}.backgrid-paginator ul>li>a:hover,.backgrid-paginator ul>.active>a,.backgrid-paginator ul>.active>span{background-color:#f5f5f5}.backgrid-paginator ul>.active>a,.backgrid-paginator ul>.active>span{color:#999;cursor:default}.backgrid-paginator ul>.disabled>span,.backgrid-paginator ul>.disabled>a,.backgrid-paginator ul>.disabled>a:hover{color:#999;cursor:default}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/css/main.css
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/css/main.css b/htrace-htraced/src/web/lib/css/main.css
deleted file mode 100644
index 1875b60..0000000
--- a/htrace-htraced/src/web/lib/css/main.css
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-ul.spans {
- margin: 0px;
- padding: 0px;
-}
-
-li.span {
- margin: 0px;
- list-style: none;
-}
-
-/* Graph */
-svg .node circle {
- stroke: #000000;
- stroke-width: 3;
- fill: #D8BFD8;
-}
-
-svg .selected circle {
- stroke-width: 3;
- fill: #DA70D6;
-}
-
-svg .link {
- stroke: black;
- stroke-width: 3;
-}
[15/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/jquery-2.1.4.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/jquery-2.1.4.js b/htrace-htraced/src/web/lib/jquery-2.1.4.js
new file mode 100644
index 0000000..eed1777
--- /dev/null
+++ b/htrace-htraced/src/web/lib/jquery-2.1.4.js
@@ -0,0 +1,9210 @@
+/*!
+ * jQuery JavaScript Library v2.1.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:01Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//
+
+var arr = [];
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ version = "2.1.4",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray,
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ // adding 1 corrects loss of precision from parseFloat (#15100)
+ return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
+ },
+
+ isPlainObject: function( obj ) {
+ // Not plain objects:
+ // - Any object or value whose internal [[Class]] property is not "[object Object]"
+ // - DOM nodes
+ // - window
+ if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.constructor &&
+ !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
+ return false;
+ }
+
+ // If the function hasn't returned already, we're confident that
+ // |obj| is a plain object, created by {} or constructed with new Object
+ return true;
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+ // Support: Android<4.0, iOS<6 (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ var script,
+ indirect = eval;
+
+ code = jQuery.trim( code );
+
+ if ( code ) {
+ // If the code includes a valid, prologue position
+ // strict mode pragma, execute code by injecting a
+ // script tag into the document.
+ if ( code.indexOf("use strict") === 1 ) {
+ script = document.createElement("script");
+ script.text = code;
+ document.head.appendChild( script ).parentNode.removeChild( script );
+ } else {
+ // Otherwise, avoid the DOM node creation, insertion
+ // and removal by using an indirect global eval
+ indirect( code );
+ }
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Support: IE9-11+
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // http://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + characterEncoding + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+ nodeType = context.nodeType;
+
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ if ( !seed && documentIsHTML ) {
+
+ // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document (jQuery #6963)
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getElementsByClassName ) {
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType !== 1 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, parent,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+ parent = doc.defaultView;
+
+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if ( parent && parent !== parent.top ) {
+ // IE11 does not have attachEvent, so all must suffer
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", unloadHandler, false );
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Support tests
+ ---------------------------------------------------------------------- */
+ documentIsHTML = !isXML( doc );
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\f]' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibing-combinator selector` fails
+ if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (oldCache = outerCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ outerCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is no seed and only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ });
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ });
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
+ });
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ }));
+};
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i,
+ len = this.length,
+ ret = [],
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], false) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], true) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Support: Blackberry 4.6
+ // gEBID returns nodes no longer in the document (#6963)
+ if ( elem && elem.parentNode ) {
+ // Inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return typeof rootjQuery.ready !== "undefined" ?
+ rootjQuery.ready( selector ) :
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ // Methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.extend({
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+ }
+});
+
+jQuery.fn.extend({
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter(function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && (pos ?
+ pos.index(cur) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector(cur, selectors)) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // Index in selector
+ if ( typeof elem === "string" ) {
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.unique(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+function sibling( cur, dir ) {
+ while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.unique( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we
<TRUNCATED>
[04/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/lib/rome-2.1.0/rome.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/lib/rome-2.1.0/rome.js b/htrace-htraced/src/web/lib/rome-2.1.0/rome.js
deleted file mode 100644
index f0b0b86..0000000
--- a/htrace-htraced/src/web/lib/rome-2.1.0/rome.js
+++ /dev/null
@@ -1,4796 +0,0 @@
-/**
- * rome - Customizable date (and time) picker. Opt-in UI, no jQuery!
- * @version v2.1.0
- * @link https://github.com/bevacqua/rome
- * @license MIT
- */
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.rome=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
-// shim for using process in browser
-
-var process = module.exports = {};
-
-process.nextTick = (function () {
- var canSetImmediate = typeof window !== 'undefined'
- && window.setImmediate;
- var canPost = typeof window !== 'undefined'
- && window.postMessage && window.addEventListener
- ;
-
- if (canSetImmediate) {
- return function (f) { return window.setImmediate(f) };
- }
-
- if (canPost) {
- var queue = [];
- window.addEventListener('message', function (ev) {
- var source = ev.source;
- if ((source === window || source === null) && ev.data === 'process-tick') {
- ev.stopPropagation();
- if (queue.length > 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
-
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
- }
-
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
-})();
-
-process.title = 'browser';
-process.browser = true;
-process.env = {};
-process.argv = [];
-
-function noop() {}
-
-process.on = noop;
-process.addListener = noop;
-process.once = noop;
-process.off = noop;
-process.removeListener = noop;
-process.removeAllListeners = noop;
-process.emit = noop;
-
-process.binding = function (name) {
- throw new Error('process.binding is not supported');
-}
-
-// TODO(shtylman)
-process.cwd = function () { return '/' };
-process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
-};
-
-},{}],2:[function(_dereq_,module,exports){
-module.exports = _dereq_('./src/contra.emitter.js');
-
-},{"./src/contra.emitter.js":3}],3:[function(_dereq_,module,exports){
-(function (process){
-(function (root, undefined) {
- 'use strict';
-
- var undef = '' + undefined;
- function atoa (a, n) { return Array.prototype.slice.call(a, n); }
- function debounce (fn, args, ctx) { if (!fn) { return; } tick(function run () { fn.apply(ctx || null, args || []); }); }
-
- // cross-platform ticker
- var si = typeof setImmediate === 'function', tick;
- if (si) {
- tick = function (fn) { setImmediate(fn); };
- } else if (typeof process !== undef && process.nextTick) {
- tick = process.nextTick;
- } else {
- tick = function (fn) { setTimeout(fn, 0); };
- }
-
- function _emitter (thing, options) {
- var opts = options || {};
- var evt = {};
- if (thing === undefined) { thing = {}; }
- thing.on = function (type, fn) {
- if (!evt[type]) {
- evt[type] = [fn];
- } else {
- evt[type].push(fn);
- }
- return thing;
- };
- thing.once = function (type, fn) {
- fn._once = true; // thing.off(fn) still works!
- thing.on(type, fn);
- return thing;
- };
- thing.off = function (type, fn) {
- var c = arguments.length;
- if (c === 1) {
- delete evt[type];
- } else if (c === 0) {
- evt = {};
- } else {
- var et = evt[type];
- if (!et) { return thing; }
- et.splice(et.indexOf(fn), 1);
- }
- return thing;
- };
- thing.emit = function () {
- var args = atoa(arguments);
- return thing.emitterSnapshot(args.shift()).apply(this, args);
- };
- thing.emitterSnapshot = function (type) {
- var et = (evt[type] || []).slice(0);
- return function () {
- var args = atoa(arguments);
- var ctx = this || thing;
- if (type === 'error' && opts.throws !== false && !et.length) { throw args.length === 1 ? args[0] : args; }
- evt[type] = et.filter(function emitter (listen) {
- if (opts.async) { debounce(listen, args, ctx); } else { listen.apply(ctx, args); }
- return !listen._once;
- });
- return thing;
- };
- }
- return thing;
- }
-
- // cross-platform export
- if (typeof module !== undef && module.exports) {
- module.exports = _emitter;
- } else {
- root.contra = root.contra || {};
- root.contra.emitter = _emitter;
- }
-})(this);
-
-}).call(this,_dereq_("FWaASH"))
-},{"FWaASH":1}],4:[function(_dereq_,module,exports){
-(function (global){
-//! moment.js
-//! version : 2.8.4
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-
-(function (undefined) {
- /************************************
- Constants
- ************************************/
-
- var moment,
- VERSION = '2.8.4',
- // the global-scope this is NOT the global object in Node.js
- globalScope = typeof global !== 'undefined' ? global : this,
- oldGlobalMoment,
- round = Math.round,
- hasOwnProperty = Object.prototype.hasOwnProperty,
- i,
-
- YEAR = 0,
- MONTH = 1,
- DATE = 2,
- HOUR = 3,
- MINUTE = 4,
- SECOND = 5,
- MILLISECOND = 6,
-
- // internal storage for locale config files
- locales = {},
-
- // extra moment internal properties (plugins register props here)
- momentProperties = [],
-
- // check for nodeJS
- hasModule = (typeof module !== 'undefined' && module && module.exports),
-
- // ASP.NET json date format regex
- aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
- aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
-
- // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
- // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
- isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
-
- // format tokens
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,
- localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
-
- // parsing token regexes
- parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
- parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
- parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
- parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
- parseTokenDigits = /\d+/, // nonzero number of digits
- parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
- parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
- parseTokenT = /T/i, // T (ISO separator)
- parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123
- parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
-
- //strict parsing regexes
- parseTokenOneDigit = /\d/, // 0 - 9
- parseTokenTwoDigits = /\d\d/, // 00 - 99
- parseTokenThreeDigits = /\d{3}/, // 000 - 999
- parseTokenFourDigits = /\d{4}/, // 0000 - 9999
- parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
- parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
-
- // iso 8601 regex
- // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
- isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
-
- isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
-
- isoDates = [
- ['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}/]
- ],
-
- // iso time formats and regexes
- isoTimes = [
- ['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/]
- ],
-
- // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30']
- parseTimezoneChunker = /([\+\-]|\d\d)/gi,
-
- // getter and setter names
- proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
- unitMillisecondFactors = {
- 'Milliseconds' : 1,
- 'Seconds' : 1e3,
- 'Minutes' : 6e4,
- 'Hours' : 36e5,
- 'Days' : 864e5,
- 'Months' : 2592e6,
- 'Years' : 31536e6
- },
-
- unitAliases = {
- 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'
- },
-
- camelFunctions = {
- dayofyear : 'dayOfYear',
- isoweekday : 'isoWeekday',
- isoweek : 'isoWeek',
- weekyear : 'weekYear',
- isoweekyear : 'isoWeekYear'
- },
-
- // format function strings
- formatFunctions = {},
-
- // default relative time thresholds
- relativeTimeThresholds = {
- s: 45, // seconds to minute
- m: 45, // minutes to hour
- h: 22, // hours to day
- d: 26, // days to month
- M: 11 // months to year
- },
-
- // tokens to ordinalize and pad
- ordinalizeTokens = 'DDD w W M D d'.split(' '),
- paddedTokens = 'M D H h m s w W'.split(' '),
-
- formatTokenFunctions = {
- M : function () {
- return this.month() + 1;
- },
- MMM : function (format) {
- return this.localeData().monthsShort(this, format);
- },
- MMMM : function (format) {
- return this.localeData().months(this, format);
- },
- D : function () {
- return this.date();
- },
- DDD : function () {
- return this.dayOfYear();
- },
- d : function () {
- return this.day();
- },
- dd : function (format) {
- return this.localeData().weekdaysMin(this, format);
- },
- ddd : function (format) {
- return this.localeData().weekdaysShort(this, format);
- },
- dddd : function (format) {
- return this.localeData().weekdays(this, format);
- },
- w : function () {
- return this.week();
- },
- W : function () {
- return this.isoWeek();
- },
- YY : function () {
- return leftZeroFill(this.year() % 100, 2);
- },
- YYYY : function () {
- return leftZeroFill(this.year(), 4);
- },
- YYYYY : function () {
- return leftZeroFill(this.year(), 5);
- },
- YYYYYY : function () {
- var y = this.year(), sign = y >= 0 ? '+' : '-';
- return sign + leftZeroFill(Math.abs(y), 6);
- },
- gg : function () {
- return leftZeroFill(this.weekYear() % 100, 2);
- },
- gggg : function () {
- return leftZeroFill(this.weekYear(), 4);
- },
- ggggg : function () {
- return leftZeroFill(this.weekYear(), 5);
- },
- GG : function () {
- return leftZeroFill(this.isoWeekYear() % 100, 2);
- },
- GGGG : function () {
- return leftZeroFill(this.isoWeekYear(), 4);
- },
- GGGGG : function () {
- return leftZeroFill(this.isoWeekYear(), 5);
- },
- e : function () {
- return this.weekday();
- },
- E : function () {
- return this.isoWeekday();
- },
- a : function () {
- return this.localeData().meridiem(this.hours(), this.minutes(), true);
- },
- A : function () {
- return this.localeData().meridiem(this.hours(), this.minutes(), false);
- },
- 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 toInt(this.milliseconds() / 100);
- },
- SS : function () {
- return leftZeroFill(toInt(this.milliseconds() / 10), 2);
- },
- SSS : function () {
- return leftZeroFill(this.milliseconds(), 3);
- },
- SSSS : function () {
- return leftZeroFill(this.milliseconds(), 3);
- },
- Z : function () {
- var a = -this.zone(),
- b = '+';
- if (a < 0) {
- a = -a;
- b = '-';
- }
- return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
- },
- ZZ : function () {
- var a = -this.zone(),
- b = '+';
- if (a < 0) {
- a = -a;
- b = '-';
- }
- return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(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();
- }
- },
-
- deprecations = {},
-
- lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
-
- // Pick the first defined of two or three arguments. dfl comes from
- // default.
- function dfl(a, b, c) {
- switch (arguments.length) {
- case 2: return a != null ? a : b;
- case 3: return a != null ? a : b != null ? b : c;
- default: throw new Error('Implement me');
- }
- }
-
- function hasOwnProp(a, b) {
- return hasOwnProperty.call(a, b);
- }
-
- function defaultParsingFlags() {
- // We need to deep clone this object, and es5 standard is not very
- // helpful.
- return {
- empty : false,
- unusedTokens : [],
- unusedInput : [],
- overflow : -2,
- charsLeftOver : 0,
- nullInput : false,
- invalidMonth : null,
- invalidFormat : false,
- userInvalidated : false,
- iso: false
- };
- }
-
- function printMsg(msg) {
- if (moment.suppressDeprecationWarnings === false &&
- typeof console !== 'undefined' && console.warn) {
- console.warn('Deprecation warning: ' + msg);
- }
- }
-
- function deprecate(msg, fn) {
- var firstTime = true;
- return extend(function () {
- if (firstTime) {
- printMsg(msg);
- firstTime = false;
- }
- return fn.apply(this, arguments);
- }, fn);
- }
-
- function deprecateSimple(name, msg) {
- if (!deprecations[name]) {
- printMsg(msg);
- deprecations[name] = true;
- }
- }
-
- function padToken(func, count) {
- return function (a) {
- return leftZeroFill(func.call(this, a), count);
- };
- }
- function ordinalizeToken(func, period) {
- return function (a) {
- return this.localeData().ordinal(func.call(this, a), period);
- };
- }
-
- while (ordinalizeTokens.length) {
- i = ordinalizeTokens.pop();
- formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
- }
- while (paddedTokens.length) {
- i = paddedTokens.pop();
- formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
- }
- formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
-
-
- /************************************
- Constructors
- ************************************/
-
- function Locale() {
- }
-
- // Moment prototype object
- function Moment(config, skipOverflow) {
- if (skipOverflow !== false) {
- checkOverflow(config);
- }
- copyConfig(this, config);
- this._d = new Date(+config._d);
- }
-
- // Duration Constructor
- function Duration(duration) {
- var normalizedInput = normalizeObjectUnits(duration),
- years = normalizedInput.year || 0,
- quarters = normalizedInput.quarter || 0,
- months = normalizedInput.month || 0,
- weeks = normalizedInput.week || 0,
- days = normalizedInput.day || 0,
- hours = normalizedInput.hour || 0,
- minutes = normalizedInput.minute || 0,
- seconds = normalizedInput.second || 0,
- milliseconds = normalizedInput.millisecond || 0;
-
- // representation for dateAddRemove
- this._milliseconds = +milliseconds +
- seconds * 1e3 + // 1000
- minutes * 6e4 + // 1000 * 60
- hours * 36e5; // 1000 * 60 * 60
- // Because of dateAddRemove treats 24 hours as different from a
- // day when working around DST, we need to store them separately
- this._days = +days +
- weeks * 7;
- // It is impossible translate months into days without knowing
- // which months you are are talking about, so we have to store
- // it separately.
- this._months = +months +
- quarters * 3 +
- years * 12;
-
- this._data = {};
-
- this._locale = moment.localeData();
-
- this._bubble();
- }
-
- /************************************
- Helpers
- ************************************/
-
-
- function extend(a, b) {
- for (var i in b) {
- if (hasOwnProp(b, i)) {
- a[i] = b[i];
- }
- }
-
- if (hasOwnProp(b, 'toString')) {
- a.toString = b.toString;
- }
-
- if (hasOwnProp(b, 'valueOf')) {
- a.valueOf = b.valueOf;
- }
-
- return a;
- }
-
- function copyConfig(to, from) {
- var i, prop, val;
-
- if (typeof from._isAMomentObject !== 'undefined') {
- to._isAMomentObject = from._isAMomentObject;
- }
- if (typeof from._i !== 'undefined') {
- to._i = from._i;
- }
- if (typeof from._f !== 'undefined') {
- to._f = from._f;
- }
- if (typeof from._l !== 'undefined') {
- to._l = from._l;
- }
- if (typeof from._strict !== 'undefined') {
- to._strict = from._strict;
- }
- if (typeof from._tzm !== 'undefined') {
- to._tzm = from._tzm;
- }
- if (typeof from._isUTC !== 'undefined') {
- to._isUTC = from._isUTC;
- }
- if (typeof from._offset !== 'undefined') {
- to._offset = from._offset;
- }
- if (typeof from._pf !== 'undefined') {
- to._pf = from._pf;
- }
- if (typeof from._locale !== 'undefined') {
- to._locale = from._locale;
- }
-
- if (momentProperties.length > 0) {
- for (i in momentProperties) {
- prop = momentProperties[i];
- val = from[prop];
- if (typeof val !== 'undefined') {
- to[prop] = val;
- }
- }
- }
-
- return to;
- }
-
- function absRound(number) {
- if (number < 0) {
- return Math.ceil(number);
- } else {
- return Math.floor(number);
- }
- }
-
- // left zero fill a number
- // see http://jsperf.com/left-zero-filling for performance comparison
- function leftZeroFill(number, targetLength, forceSign) {
- var output = '' + Math.abs(number),
- sign = number >= 0;
-
- while (output.length < targetLength) {
- output = '0' + output;
- }
- return (sign ? (forceSign ? '+' : '') : '-') + output;
- }
-
- function positiveMomentsDifference(base, other) {
- var res = {milliseconds: 0, months: 0};
-
- res.months = other.month() - base.month() +
- (other.year() - base.year()) * 12;
- if (base.clone().add(res.months, 'M').isAfter(other)) {
- --res.months;
- }
-
- res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
-
- return res;
- }
-
- function momentsDifference(base, other) {
- var res;
- other = makeAs(other, base);
- if (base.isBefore(other)) {
- res = positiveMomentsDifference(base, other);
- } else {
- res = positiveMomentsDifference(other, base);
- res.milliseconds = -res.milliseconds;
- res.months = -res.months;
- }
-
- return res;
- }
-
- // TODO: remove 'name' arg after deprecation is removed
- function createAdder(direction, name) {
- return function (val, period) {
- var dur, tmp;
- //invert the arguments, but complain about it
- if (period !== null && !isNaN(+period)) {
- deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
- tmp = val; val = period; period = tmp;
- }
-
- val = typeof val === 'string' ? +val : val;
- dur = moment.duration(val, period);
- addOrSubtractDurationFromMoment(this, dur, direction);
- return this;
- };
- }
-
- function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
- var milliseconds = duration._milliseconds,
- days = duration._days,
- months = duration._months;
- updateOffset = updateOffset == null ? true : updateOffset;
-
- if (milliseconds) {
- mom._d.setTime(+mom._d + milliseconds * isAdding);
- }
- if (days) {
- rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
- }
- if (months) {
- rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
- }
- if (updateOffset) {
- moment.updateOffset(mom, days || months);
- }
- }
-
- // check if is an array
- function isArray(input) {
- return Object.prototype.toString.call(input) === '[object Array]';
- }
-
- function isDate(input) {
- return Object.prototype.toString.call(input) === '[object Date]' ||
- input instanceof Date;
- }
-
- // compare two arrays, return the number of differences
- function compareArrays(array1, array2, dontConvert) {
- var len = Math.min(array1.length, array2.length),
- lengthDiff = Math.abs(array1.length - array2.length),
- diffs = 0,
- i;
- for (i = 0; i < len; i++) {
- if ((dontConvert && array1[i] !== array2[i]) ||
- (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
- diffs++;
- }
- }
- return diffs + lengthDiff;
- }
-
- function normalizeUnits(units) {
- if (units) {
- var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
- units = unitAliases[units] || camelFunctions[lowered] || lowered;
- }
- return units;
- }
-
- function normalizeObjectUnits(inputObject) {
- var normalizedInput = {},
- normalizedProp,
- prop;
-
- for (prop in inputObject) {
- if (hasOwnProp(inputObject, prop)) {
- normalizedProp = normalizeUnits(prop);
- if (normalizedProp) {
- normalizedInput[normalizedProp] = inputObject[prop];
- }
- }
- }
-
- return normalizedInput;
- }
-
- function makeList(field) {
- var count, setter;
-
- if (field.indexOf('week') === 0) {
- count = 7;
- setter = 'day';
- }
- else if (field.indexOf('month') === 0) {
- count = 12;
- setter = 'month';
- }
- else {
- return;
- }
-
- moment[field] = function (format, index) {
- var i, getter,
- method = moment._locale[field],
- results = [];
-
- if (typeof format === 'number') {
- index = format;
- format = undefined;
- }
-
- getter = function (i) {
- var m = moment().utc().set(setter, i);
- return method.call(moment._locale, m, format || '');
- };
-
- if (index != null) {
- return getter(index);
- }
- else {
- for (i = 0; i < count; i++) {
- results.push(getter(i));
- }
- return results;
- }
- };
- }
-
- function toInt(argumentForCoercion) {
- var coercedNumber = +argumentForCoercion,
- value = 0;
-
- if (coercedNumber !== 0 && isFinite(coercedNumber)) {
- if (coercedNumber >= 0) {
- value = Math.floor(coercedNumber);
- } else {
- value = Math.ceil(coercedNumber);
- }
- }
-
- return value;
- }
-
- function daysInMonth(year, month) {
- return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
- }
-
- function weeksInYear(year, dow, doy) {
- return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
- }
-
- function daysInYear(year) {
- return isLeapYear(year) ? 366 : 365;
- }
-
- function isLeapYear(year) {
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
- }
-
- function checkOverflow(m) {
- var overflow;
- if (m._a && m._pf.overflow === -2) {
- overflow =
- m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
- m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
- m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
- (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
- m._a[SECOND] !== 0 ||
- m._a[MILLISECOND] !== 0)) ? HOUR :
- m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
- m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
- m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
- -1;
-
- if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
- overflow = DATE;
- }
-
- m._pf.overflow = overflow;
- }
- }
-
- function isValid(m) {
- if (m._isValid == null) {
- m._isValid = !isNaN(m._d.getTime()) &&
- m._pf.overflow < 0 &&
- !m._pf.empty &&
- !m._pf.invalidMonth &&
- !m._pf.nullInput &&
- !m._pf.invalidFormat &&
- !m._pf.userInvalidated;
-
- if (m._strict) {
- m._isValid = m._isValid &&
- m._pf.charsLeftOver === 0 &&
- m._pf.unusedTokens.length === 0 &&
- m._pf.bigHour === undefined;
- }
- }
- return m._isValid;
- }
-
- function normalizeLocale(key) {
- return key ? key.toLowerCase().replace('_', '-') : key;
- }
-
- // pick the locale from the array
- // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
- // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
- function chooseLocale(names) {
- var i = 0, j, next, locale, split;
-
- while (i < names.length) {
- split = normalizeLocale(names[i]).split('-');
- j = split.length;
- next = normalizeLocale(names[i + 1]);
- next = next ? next.split('-') : null;
- while (j > 0) {
- locale = loadLocale(split.slice(0, j).join('-'));
- if (locale) {
- return locale;
- }
- if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
- //the next array item is better than a shallower substring of this one
- break;
- }
- j--;
- }
- i++;
- }
- return null;
- }
-
- function loadLocale(name) {
- var oldLocale = null;
- if (!locales[name] && hasModule) {
- try {
- oldLocale = moment.locale();
- _dereq_('./locale/' + name);
- // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
- moment.locale(oldLocale);
- } catch (e) { }
- }
- return locales[name];
- }
-
- // Return a moment from input, that is local/utc/zone equivalent to model.
- function makeAs(input, model) {
- var res, diff;
- if (model._isUTC) {
- res = model.clone();
- diff = (moment.isMoment(input) || isDate(input) ?
- +input : +moment(input)) - (+res);
- // Use low-level api, because this fn is low-level api.
- res._d.setTime(+res._d + diff);
- moment.updateOffset(res, false);
- return res;
- } else {
- return moment(input).local();
- }
- }
-
- /************************************
- Locale
- ************************************/
-
-
- extend(Locale.prototype, {
-
- set : function (config) {
- var prop, i;
- for (i in config) {
- prop = config[i];
- if (typeof prop === 'function') {
- this[i] = prop;
- } else {
- this['_' + i] = prop;
- }
- }
- // Lenient ordinal parsing accepts just a number in addition to
- // number + (possibly) stuff coming from _ordinalParseLenient.
- 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 (m) {
- return this._months[m.month()];
- },
-
- _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
- monthsShort : function (m) {
- return this._monthsShort[m.month()];
- },
-
- monthsParse : function (monthName, format, strict) {
- var i, mom, regex;
-
- if (!this._monthsParse) {
- this._monthsParse = [];
- this._longMonthsParse = [];
- this._shortMonthsParse = [];
- }
-
- for (i = 0; i < 12; i++) {
- // make the regex if we don't have it already
- mom = moment.utc([2000, i]);
- if (strict && !this._longMonthsParse[i]) {
- this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
- this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
- }
- if (!strict && !this._monthsParse[i]) {
- regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
- this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
- }
- // test the regex
- if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
- return i;
- } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
- return i;
- } else if (!strict && this._monthsParse[i].test(monthName)) {
- return i;
- }
- }
- },
-
- _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
- weekdays : function (m) {
- return this._weekdays[m.day()];
- },
-
- _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
- weekdaysShort : function (m) {
- return this._weekdaysShort[m.day()];
- },
-
- _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
- weekdaysMin : function (m) {
- return this._weekdaysMin[m.day()];
- },
-
- weekdaysParse : function (weekdayName) {
- var i, mom, regex;
-
- if (!this._weekdaysParse) {
- this._weekdaysParse = [];
- }
-
- for (i = 0; i < 7; i++) {
- // make the regex if we don't have it already
- if (!this._weekdaysParse[i]) {
- mom = moment([2000, 1]).day(i);
- regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
- this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
- }
- // test the regex
- if (this._weekdaysParse[i].test(weekdayName)) {
- return i;
- }
- }
- },
-
- _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 (key) {
- var output = this._longDateFormat[key];
- if (!output && this._longDateFormat[key.toUpperCase()]) {
- output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
- return val.slice(1);
- });
- this._longDateFormat[key] = output;
- }
- return output;
- },
-
- isPM : function (input) {
- // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
- // Using charAt should be more compatible.
- return ((input + '').toLowerCase().charAt(0) === 'p');
- },
-
- _meridiemParse : /[ap]\.?m?\.?/i,
- meridiem : function (hours, minutes, isLower) {
- if (hours > 11) {
- return isLower ? 'pm' : 'PM';
- } else {
- return isLower ? '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 (key, mom, now) {
- var output = this._calendar[key];
- return typeof output === 'function' ? output.apply(mom, [now]) : output;
- },
-
- _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 (number, withoutSuffix, string, isFuture) {
- var output = this._relativeTime[string];
- return (typeof output === 'function') ?
- output(number, withoutSuffix, string, isFuture) :
- output.replace(/%d/i, number);
- },
-
- pastFuture : function (diff, output) {
- var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
- return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
- },
-
- ordinal : function (number) {
- return this._ordinal.replace('%d', number);
- },
- _ordinal : '%d',
- _ordinalParse : /\d{1,2}/,
-
- preparse : function (string) {
- return string;
- },
-
- postformat : function (string) {
- return string;
- },
-
- week : function (mom) {
- return weekOfYear(mom, this._week.dow, this._week.doy).week;
- },
-
- _week : {
- dow : 0, // Sunday is the first day of the week.
- doy : 6 // The week that contains Jan 1st is the first week of the year.
- },
-
- _invalidDate: 'Invalid date',
- invalidDate: function () {
- return this._invalidDate;
- }
- });
-
- /************************************
- Formatting
- ************************************/
-
-
- function removeFormattingTokens(input) {
- if (input.match(/\[[\s\S]/)) {
- return input.replace(/^\[|\]$/g, '');
- }
- return input.replace(/\\/g, '');
- }
-
- function makeFormatFunction(format) {
- var array = format.match(formattingTokens), i, length;
-
- for (i = 0, length = array.length; i < length; i++) {
- if (formatTokenFunctions[array[i]]) {
- array[i] = formatTokenFunctions[array[i]];
- } else {
- array[i] = removeFormattingTokens(array[i]);
- }
- }
-
- return function (mom) {
- var output = '';
- for (i = 0; i < length; i++) {
- output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
- }
- return output;
- };
- }
-
- // format date using native date object
- function formatMoment(m, format) {
- if (!m.isValid()) {
- return m.localeData().invalidDate();
- }
-
- format = expandFormat(format, m.localeData());
-
- if (!formatFunctions[format]) {
- formatFunctions[format] = makeFormatFunction(format);
- }
-
- return formatFunctions[format](m);
- }
-
- function expandFormat(format, locale) {
- var i = 5;
-
- function replaceLongDateFormatTokens(input) {
- return locale.longDateFormat(input) || input;
- }
-
- localFormattingTokens.lastIndex = 0;
- while (i >= 0 && localFormattingTokens.test(format)) {
- format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
- localFormattingTokens.lastIndex = 0;
- i -= 1;
- }
-
- return format;
- }
-
-
- /************************************
- Parsing
- ************************************/
-
-
- // get the regex to find the next token
- function getParseRegexForToken(token, config) {
- var a, strict = config._strict;
- switch (token) {
- case 'Q':
- return parseTokenOneDigit;
- case 'DDDD':
- return parseTokenThreeDigits;
- case 'YYYY':
- case 'GGGG':
- case 'gggg':
- return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
- case 'Y':
- case 'G':
- case 'g':
- return parseTokenSignedNumber;
- case 'YYYYYY':
- case 'YYYYY':
- case 'GGGGG':
- case 'ggggg':
- return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
- case 'S':
- if (strict) {
- return parseTokenOneDigit;
- }
- /* falls through */
- case 'SS':
- if (strict) {
- return parseTokenTwoDigits;
- }
- /* falls through */
- case 'SSS':
- if (strict) {
- return parseTokenThreeDigits;
- }
- /* falls through */
- case 'DDD':
- return parseTokenOneToThreeDigits;
- case 'MMM':
- case 'MMMM':
- case 'dd':
- case 'ddd':
- case 'dddd':
- return parseTokenWord;
- case 'a':
- case 'A':
- return config._locale._meridiemParse;
- case 'x':
- return parseTokenOffsetMs;
- case 'X':
- return parseTokenTimestampMs;
- case 'Z':
- case 'ZZ':
- return parseTokenTimezone;
- case 'T':
- return parseTokenT;
- case 'SSSS':
- return parseTokenDigits;
- case 'MM':
- case 'DD':
- case 'YY':
- case 'GG':
- case 'gg':
- case 'HH':
- case 'hh':
- case 'mm':
- case 'ss':
- case 'ww':
- case 'WW':
- return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
- case 'M':
- case 'D':
- case 'd':
- case 'H':
- case 'h':
- case 'm':
- case 's':
- case 'w':
- case 'W':
- case 'e':
- case 'E':
- return parseTokenOneOrTwoDigits;
- case 'Do':
- return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
- default :
- a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
- return a;
- }
- }
-
- function timezoneMinutesFromString(string) {
- string = string || '';
- var possibleTzMatches = (string.match(parseTokenTimezone) || []),
- tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
- parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
- minutes = +(parts[1] * 60) + toInt(parts[2]);
-
- return parts[0] === '+' ? -minutes : minutes;
- }
-
- // function to convert string input to date
- function addTimeToArrayFromToken(token, input, config) {
- var a, datePartArray = config._a;
-
- switch (token) {
- // QUARTER
- case 'Q':
- if (input != null) {
- datePartArray[MONTH] = (toInt(input) - 1) * 3;
- }
- break;
- // MONTH
- case 'M' : // fall through to MM
- case 'MM' :
- if (input != null) {
- datePartArray[MONTH] = toInt(input) - 1;
- }
- break;
- case 'MMM' : // fall through to MMMM
- case 'MMMM' :
- a = config._locale.monthsParse(input, token, config._strict);
- // if we didn't find a month name, mark the date as invalid.
- if (a != null) {
- datePartArray[MONTH] = a;
- } else {
- config._pf.invalidMonth = input;
- }
- break;
- // DAY OF MONTH
- case 'D' : // fall through to DD
- case 'DD' :
- if (input != null) {
- datePartArray[DATE] = toInt(input);
- }
- break;
- case 'Do' :
- if (input != null) {
- datePartArray[DATE] = toInt(parseInt(
- input.match(/\d{1,2}/)[0], 10));
- }
- break;
- // DAY OF YEAR
- case 'DDD' : // fall through to DDDD
- case 'DDDD' :
- if (input != null) {
- config._dayOfYear = toInt(input);
- }
-
- break;
- // YEAR
- case 'YY' :
- datePartArray[YEAR] = moment.parseTwoDigitYear(input);
- break;
- case 'YYYY' :
- case 'YYYYY' :
- case 'YYYYYY' :
- datePartArray[YEAR] = toInt(input);
- break;
- // AM / PM
- case 'a' : // fall through to A
- case 'A' :
- config._isPm = config._locale.isPM(input);
- break;
- // HOUR
- case 'h' : // fall through to hh
- case 'hh' :
- config._pf.bigHour = true;
- /* falls through */
- case 'H' : // fall through to HH
- case 'HH' :
- datePartArray[HOUR] = toInt(input);
- break;
- // MINUTE
- case 'm' : // fall through to mm
- case 'mm' :
- datePartArray[MINUTE] = toInt(input);
- break;
- // SECOND
- case 's' : // fall through to ss
- case 'ss' :
- datePartArray[SECOND] = toInt(input);
- break;
- // MILLISECOND
- case 'S' :
- case 'SS' :
- case 'SSS' :
- case 'SSSS' :
- datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
- break;
- // UNIX OFFSET (MILLISECONDS)
- case 'x':
- config._d = new Date(toInt(input));
- break;
- // UNIX TIMESTAMP WITH MS
- case 'X':
- config._d = new Date(parseFloat(input) * 1000);
- break;
- // TIMEZONE
- case 'Z' : // fall through to ZZ
- case 'ZZ' :
- config._useUTC = true;
- config._tzm = timezoneMinutesFromString(input);
- break;
- // WEEKDAY - human
- case 'dd':
- case 'ddd':
- case 'dddd':
- a = config._locale.weekdaysParse(input);
- // if we didn't get a weekday name, mark the date as invalid
- if (a != null) {
- config._w = config._w || {};
- config._w['d'] = a;
- } else {
- config._pf.invalidWeekday = input;
- }
- break;
- // WEEK, WEEK DAY - numeric
- case 'w':
- case 'ww':
- case 'W':
- case 'WW':
- case 'd':
- case 'e':
- case 'E':
- token = token.substr(0, 1);
- /* falls through */
- case 'gggg':
- case 'GGGG':
- case 'GGGGG':
- token = token.substr(0, 2);
- if (input) {
- config._w = config._w || {};
- config._w[token] = toInt(input);
- }
- break;
- case 'gg':
- case 'GG':
- config._w = config._w || {};
- config._w[token] = moment.parseTwoDigitYear(input);
- }
- }
-
- function dayOfYearFromWeekInfo(config) {
- var w, weekYear, week, weekday, dow, doy, temp;
-
- w = config._w;
- if (w.GG != null || w.W != null || w.E != null) {
- dow = 1;
- doy = 4;
-
- // TODO: We need to take the current isoWeekYear, but that depends on
- // how we interpret now (local, utc, fixed offset). So create
- // a now version of current config (take local/utc/offset flags, and
- // create now).
- weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
- week = dfl(w.W, 1);
- weekday = dfl(w.E, 1);
- } else {
- dow = config._locale._week.dow;
- doy = config._locale._week.doy;
-
- weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
- week = dfl(w.w, 1);
-
- if (w.d != null) {
- // weekday -- low day numbers are considered next week
- weekday = w.d;
- if (weekday < dow) {
- ++week;
- }
- } else if (w.e != null) {
- // local weekday -- counting starts from begining of week
- weekday = w.e + dow;
- } else {
- // default to begining of week
- weekday = dow;
- }
- }
- temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
-
- config._a[YEAR] = temp.year;
- config._dayOfYear = temp.dayOfYear;
- }
-
- // convert an array to a date.
- // the array should mirror the parameters below
- // note: all values past the year are optional and will default to the lowest possible value.
- // [year, month, day , hour, minute, second, millisecond]
- function dateFromConfig(config) {
- var i, date, input = [], currentDate, yearToUse;
-
- if (config._d) {
- return;
- }
-
- currentDate = currentDateArray(config);
-
- //compute day of the year from weeks and weekdays
- if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
- dayOfYearFromWeekInfo(config);
- }
-
- //if the day of the year is set, figure out what it is
- if (config._dayOfYear) {
- yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
-
- if (config._dayOfYear > daysInYear(yearToUse)) {
- config._pf._overflowDayOfYear = true;
- }
-
- date = makeUTCDate(yearToUse, 0, config._dayOfYear);
- config._a[MONTH] = date.getUTCMonth();
- config._a[DATE] = date.getUTCDate();
- }
-
- // Default to current date.
- // * if no year, month, day of month are given, default to today
- // * if day of month is given, default month and year
- // * if month is given, default only year
- // * if year is given, don't default anything
- for (i = 0; i < 3 && config._a[i] == null; ++i) {
- config._a[i] = input[i] = currentDate[i];
- }
-
- // Zero out whatever was not defaulted, including time
- for (; i < 7; i++) {
- config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
- }
-
- // Check for 24:00:00.000
- if (config._a[HOUR] === 24 &&
- config._a[MINUTE] === 0 &&
- config._a[SECOND] === 0 &&
- config._a[MILLISECOND] === 0) {
- config._nextDay = true;
- config._a[HOUR] = 0;
- }
-
- config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
- // Apply timezone offset from input. The actual zone can be changed
- // with parseZone.
- if (config._tzm != null) {
- config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm);
- }
-
- if (config._nextDay) {
- config._a[HOUR] = 24;
- }
- }
-
- function dateFromObject(config) {
- var normalizedInput;
-
- if (config._d) {
- return;
- }
-
- normalizedInput = normalizeObjectUnits(config._i);
- config._a = [
- normalizedInput.year,
- normalizedInput.month,
- normalizedInput.day || normalizedInput.date,
- normalizedInput.hour,
- normalizedInput.minute,
- normalizedInput.second,
- normalizedInput.millisecond
- ];
-
- dateFromConfig(config);
- }
-
- function currentDateArray(config) {
- var now = new Date();
- if (config._useUTC) {
- return [
- now.getUTCFullYear(),
- now.getUTCMonth(),
- now.getUTCDate()
- ];
- } else {
- return [now.getFullYear(), now.getMonth(), now.getDate()];
- }
- }
-
- // date from string and format string
- function makeDateFromStringAndFormat(config) {
- if (config._f === moment.ISO_8601) {
- parseISO(config);
- return;
- }
-
- config._a = [];
- config._pf.empty = true;
-
- // This array is used to make a Date, either with `new Date` or `Date.UTC`
- var string = '' + config._i,
- i, parsedInput, tokens, token, skipped,
- stringLength = string.length,
- totalParsedInputLength = 0;
-
- tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
-
- for (i = 0; i < tokens.length; i++) {
- token = tokens[i];
- parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
- if (parsedInput) {
- skipped = string.substr(0, string.indexOf(parsedInput));
- if (skipped.length > 0) {
- config._pf.unusedInput.push(skipped);
- }
- string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
- totalParsedInputLength += parsedInput.length;
- }
- // don't parse if it's not a known token
- if (formatTokenFunctions[token]) {
- if (parsedInput) {
- config._pf.empty = false;
- }
- else {
- config._pf.unusedTokens.push(token);
- }
- addTimeToArrayFromToken(token, parsedInput, config);
- }
- else if (config._strict && !parsedInput) {
- config._pf.unusedTokens.push(token);
- }
- }
-
- // add remaining unparsed input length to the string
- config._pf.charsLeftOver = stringLength - totalParsedInputLength;
- if (string.length > 0) {
- config._pf.unusedInput.push(string);
- }
-
- // clear _12h flag if hour is <= 12
- if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
- config._pf.bigHour = undefined;
- }
- // handle am pm
- if (config._isPm && config._a[HOUR] < 12) {
- config._a[HOUR] += 12;
- }
- // if is 12 am, change hours to 0
- if (config._isPm === false && config._a[HOUR] === 12) {
- config._a[HOUR] = 0;
- }
- dateFromConfig(config);
- checkOverflow(config);
- }
-
- function unescapeFormat(s) {
- return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
- return p1 || p2 || p3 || p4;
- });
- }
-
- // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
- function regexpEscape(s) {
- return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
- }
-
- // date from string and array of format strings
- function makeDateFromStringAndArray(config) {
- var tempConfig,
- bestMoment,
-
- scoreToBeat,
- i,
- currentScore;
-
- if (config._f.length === 0) {
- config._pf.invalidFormat = true;
- config._d = new Date(NaN);
- return;
- }
-
- for (i = 0; i < config._f.length; i++) {
- currentScore = 0;
- tempConfig = copyConfig({}, config);
- if (config._useUTC != null) {
- tempConfig._useUTC = config._useUTC;
- }
- tempConfig._pf = defaultParsingFlags();
- tempConfig._f = config._f[i];
- makeDateFromStringAndFormat(tempConfig);
-
- if (!isValid(tempConfig)) {
- continue;
- }
-
- // if there is any input that was not parsed add a penalty for that format
- currentScore += tempConfig._pf.charsLeftOver;
-
- //or tokens
- currentScore += tempConfig._pf.unusedTokens.length * 10;
-
- tempConfig._pf.score = currentScore;
-
- if (scoreToBeat == null || currentScore < scoreToBeat) {
- scoreToBeat = currentScore;
- bestMoment = tempConfig;
- }
- }
-
- extend(config, bestMoment || tempConfig);
- }
-
- // date from iso format
- function parseISO(config) {
- var i, l,
- string = config._i,
- match = isoRegex.exec(string);
-
- if (match) {
- config._pf.iso = true;
- for (i = 0, l = isoDates.length; i < l; i++) {
- if (isoDates[i][1].exec(string)) {
- // match[5] should be 'T' or undefined
- config._f = isoDates[i][0] + (match[6] || ' ');
- break;
- }
- }
- for (i = 0, l = isoTimes.length; i < l; i++) {
- if (isoTimes[i][1].exec(string)) {
- config._f += isoTimes[i][0];
- break;
- }
- }
- if (string.match(parseTokenTimezone)) {
- config._f += 'Z';
- }
- makeDateFromStringAndFormat(config);
- } else {
- config._isValid = false;
- }
- }
-
- // date from iso format or fallback
- function makeDateFromString(config) {
- parseISO(config);
- if (config._isValid === false) {
- delete config._isValid;
- moment.createFromInputFallback(config);
- }
- }
-
- function map(arr, fn) {
- var res = [], i;
- for (i = 0; i < arr.length; ++i) {
- res.push(fn(arr[i], i));
- }
- return res;
- }
-
- function makeDateFromInput(config) {
- var input = config._i, matched;
- if (input === undefined) {
- config._d = new Date();
- } else if (isDate(input)) {
- config._d = new Date(+input);
- } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
- config._d = new Date(+matched[1]);
- } else if (typeof input === 'string') {
- makeDateFromString(config);
- } else if (isArray(input)) {
- config._a = map(input.slice(0), function (obj) {
- return parseInt(obj, 10);
- });
- dateFromConfig(config);
- } else if (typeof(input) === 'object') {
- dateFromObject(config);
- } else if (typeof(input) === 'number') {
- // from milliseconds
- config._d = new Date(input);
- } else {
- moment.createFromInputFallback(config);
- }
- }
-
- function makeDate(y, m, d, h, M, s, ms) {
- //can't just apply() to create a date:
- //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
- var date = new Date(y, m, d, h, M, s, ms);
-
- //the date constructor doesn't accept years < 1970
- if (y < 1970) {
- date.setFullYear(y);
- }
- return date;
- }
-
- function makeUTCDate(y) {
- var date = new Date(Date.UTC.apply(null, arguments));
- if (y < 1970) {
- date.setUTCFullYear(y);
- }
- return date;
- }
-
- function parseWeekday(input, locale) {
- if (typeof input === 'string') {
- if (!isNaN(input)) {
- input = parseInt(input, 10);
- }
- else {
- input = locale.weekdaysParse(input);
- if (typeof input !== 'number') {
- return null;
- }
- }
- }
- return input;
- }
-
- /************************************
- Relative Time
- ************************************/
-
-
- // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
- function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
- return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
- }
-
- function relativeTime(posNegDuration, withoutSuffix, locale) {
- var duration = moment.duration(posNegDuration).abs(),
- seconds = round(duration.as('s')),
- minutes = round(duration.as('m')),
- hours = round(duration.as('h')),
- days = round(duration.as('d')),
- months = round(duration.as('M')),
- years = round(duration.as('y')),
-
- args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
- minutes === 1 && ['m'] ||
- minutes < relativeTimeThresholds.m && ['mm', minutes] ||
- hours === 1 && ['h'] ||
- hours < relativeTimeThresholds.h && ['hh', hours] ||
- days === 1 && ['d'] ||
- days < relativeTimeThresholds.d && ['dd', days] ||
- months === 1 && ['M'] ||
- months < relativeTimeThresholds.M && ['MM', months] ||
- years === 1 && ['y'] || ['yy', years];
-
- args[2] = withoutSuffix;
- args[3] = +posNegDuration > 0;
- args[4] = locale;
- return substituteTimeAgo.apply({}, args);
- }
-
-
- /************************************
- Week of Year
- ************************************/
-
-
- // firstDayOfWeek 0 = sun, 6 = sat
- // the day of the week that starts the week
- // (usually sunday or monday)
- // firstDayOfWeekOfYear 0 = sun, 6 = sat
- // the first week is the week that contains the first
- // of this day of the week
- // (eg. ISO weeks use thursday (4))
- function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
- var end = firstDayOfWeekOfYear - firstDayOfWeek,
- daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
- adjustedMoment;
-
-
- if (daysToDayOfWeek > end) {
- daysToDayOfWeek -= 7;
- }
-
- if (daysToDayOfWeek < end - 7) {
- daysToDayOfWeek += 7;
- }
-
- adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
- return {
- week: Math.ceil(adjustedMoment.dayOfYear() / 7),
- year: adjustedMoment.year()
- };
- }
-
- //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
- function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
- var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
-
- d = d === 0 ? 7 : d;
- weekday = weekday != null ? weekday : firstDayOfWeek;
- daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
- dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
-
- return {
- year: dayOfYear > 0 ? year : year - 1,
- dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
- };
- }
-
- /************************************
- Top Level Functions
- ************************************/
-
- function makeMoment(config) {
- var input = config._i,
- format = config._f,
- res;
-
- config._locale = config._locale || moment.localeData(config._l);
-
- if (input === null || (format === undefined && input === '')) {
- return moment.invalid({nullInput: true});
- }
-
- if (typeof input === 'string') {
- config._i = input = config._locale.preparse(input);
- }
-
- if (moment.isMoment(input)) {
- return new Moment(input, true);
- } else if (format) {
- if (isArray(format)) {
- makeDateFromStringAndArray(config);
- } else {
- makeDateFromStringAndFormat(config);
- }
- } else {
- makeDateFromInput(config);
- }
-
- res = new Moment(config);
- if (res._nextDay) {
- // Adding is smart enough around DST
- res.add(1, 'd');
- res._nextDay = undefined;
- }
-
- return res;
- }
-
- moment = function (input, format, locale, strict) {
- var c;
-
- if (typeof(locale) === 'boolean') {
- strict = locale;
- locale = undefined;
- }
- // object construction must be done this way.
- // https://github.com/moment/moment/issues/1423
- c = {};
- c._isAMomentObject = true;
- c._i = input;
- c._f = format;
- c._l = locale;
- c._strict = strict;
- c._isUTC = false;
- c._pf = defaultParsingFlags();
-
- return makeMoment(c);
- };
-
- moment.suppressDeprecationWarnings = false;
-
- moment.createFromInputFallback = deprecate(
- '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 (config) {
- config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
- }
- );
-
- // Pick a moment m from moments so that m[fn](other) is true for all
- // other. This relies on the function fn to be transitive.
- //
- // moments should either be an array of moment objects or an array, whose
- // first element is an array of moment objects.
- function pickBy(fn, moments) {
- var res, i;
- if (moments.length === 1 && isArray(moments[0])) {
- moments = moments[0];
- }
- if (!moments.length) {
- return moment();
- }
- res = moments[0];
- for (i = 1; i < moments.length; ++i) {
- if (moments[i][fn](res)) {
- res = moments[i];
- }
- }
- return res;
- }
-
- moment.min = function () {
- var args = [].slice.call(arguments, 0);
-
- return pickBy('isBefore', args);
- };
-
- moment.max = function () {
- var args = [].slice.call(arguments, 0);
-
- return pickBy('isAfter', args);
- };
-
- // creating with utc
- moment.utc = function (input, format, locale, strict) {
- var c;
-
- if (typeof(locale) === 'boolean') {
- strict = locale;
- locale = undefined;
- }
- // object construction must be done this way.
- // https://github.com/moment/moment/issues/1423
- c = {};
- c._isAMomentObject = true;
- c._useUTC = true;
- c._isUTC = true;
- c._l = locale;
- c._i = input;
- c._f = format;
- c._strict = strict;
- c._pf = defaultParsingFlags();
-
- return makeMoment(c).utc();
- };
-
- // creating with unix timestamp (in seconds)
- moment.unix = function (input) {
- return moment(input * 1000);
- };
-
- // duration
- moment.duration = function (input, key) {
- var duration = input,
- // matching against regexp is expensive, do it on demand
- match = null,
- sign,
- ret,
- parseIso,
- diffRes;
-
- if (moment.isDuration(input)) {
- duration = {
- ms: input._milliseconds,
- d: input._days,
- M: input._months
- };
- } else if (typeof input === 'number') {
- duration = {};
- if (key) {
- duration[key] = input;
- } else {
- duration.milliseconds = input;
- }
- } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
- sign = (match[1] === '-') ? -1 : 1;
- duration = {
- y: 0,
- d: toInt(match[DATE]) * sign,
- h: toInt(match[HOUR]) * sign,
- m: toInt(match[MINUTE]) * sign,
- s: toInt(match[SECOND]) * sign,
- ms: toInt(match[MILLISECOND]) * sign
- };
- } else if (!!(match = isoDurationRegex.exec(input))) {
- sign = (match[1] === '-') ? -1 : 1;
- parseIso = function (inp) {
- // We'd normally use ~~inp for this, but unfortunately it also
- // converts floats to ints.
- // inp may be undefined, so careful calling replace on it.
- var res = inp && parseFloat(inp.replace(',', '.'));
- // apply sign while we're at it
- return (isNaN(res) ? 0 : res) * sign;
- };
- duration = {
- y: parseIso(match[2]),
- M: parseIso(match[3]),
- d: parseIso(match[4]),
- h: parseIso(match[5]),
- m: parseIso(match[6]),
- s: parseIso(match[7]),
- w: parseIso(match[8])
- };
- } else if (typeof duration === 'object' &&
- ('from' in duration || 'to' in duration)) {
- diffRes = momentsDifference(moment(duration.from), moment(duration.to));
-
- duration = {};
- duration.ms = diffRes.milliseconds;
- duration.M = diffRes.months;
- }
-
- ret = new Duration(duration);
-
- if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
- ret._locale = input._locale;
- }
-
- return ret;
- };
-
- // version number
- moment.version = VERSION;
-
- // default format
- moment.defaultFormat = isoFormat;
-
- // constant that refers to the ISO standard
- moment.ISO_8601 = function () {};
-
- // Plugins that add properties should also add the key here (null value),
- // so we can properly clone ourselves.
- moment.momentProperties = momentProperties;
-
- // This function will be called whenever a moment is mutated.
- // It is intended to keep the offset in sync with the timezone.
- moment.updateOffset = function () {};
-
- // This function allows you to set a threshold for relative time strings
- moment.relativeTimeThreshold = function (threshold, limit) {
- if (relativeTimeThresholds[threshold] === undefined) {
- return false;
- }
- if (limit === undefined) {
- return relativeTimeThresholds[threshold];
- }
- relativeTimeThresholds[threshold] = limit;
- return true;
- };
-
- moment.lang = deprecate(
- 'moment.lang is deprecated. Use moment.locale instead.',
- function (key, value) {
- return moment.locale(key, value);
- }
- );
-
- // This function will load locale and then set the global locale. If
- // no arguments are passed in, it will simply return the current global
- // locale key.
- moment.locale = function (key, values) {
- var data;
- if (key) {
- if (typeof(values) !== 'undefined') {
- data = moment.defineLocale(key, values);
- }
- else {
- data = moment.localeData(key);
- }
-
- if (data) {
- moment.duration._locale = moment._locale = data;
- }
- }
-
- return moment._locale._abbr;
- };
-
- moment.defineLocale = function (name, values) {
- if (values !== null) {
- values.abbr = name;
- if (!locales[name]) {
- locales[name] = new Locale();
- }
- locales[name].set(values);
-
- // backwards compat for now: also set the locale
- moment.locale(name);
-
- return locales[name];
- } else {
- // useful for testing
- delete locales[name];
- return null;
- }
- };
-
- moment.langData = deprecate(
- 'moment.langData is deprecated. Use moment.localeData instead.',
- function (key) {
- return moment.localeData(key);
- }
- );
-
- // returns locale data
- moment.localeData = function (key) {
- var locale;
-
- if (key && key._locale && key._locale._abbr) {
- key = key._locale._abbr;
- }
-
- if (!key) {
- return moment._locale;
- }
-
- if (!isArray(key)) {
- //short-circuit everything else
- locale = loadLocale(key);
- if (locale) {
- return locale;
- }
- key = [key];
- }
-
- return chooseLocale(key);
- };
-
- // compare moment object
- moment.isMoment = function (obj) {
- return obj instanceof Moment ||
- (obj != null && hasOwnProp(obj, '_isAMomentObject'));
- };
-
- // for typechecking Duration objects
- moment.isDuration = function (obj) {
- return obj instanceof Duration;
- };
-
- for (i = lists.length - 1; i >= 0; --i) {
- makeList(lists[i]);
- }
-
- moment.normalizeUnits = function (units) {
- return normalizeUnits(units);
- };
-
- moment.invalid = function (flags) {
- var m = moment.utc(NaN);
- if (flags != null) {
- extend(m._pf, flags);
- }
- else {
- m._pf.userInvalidated = true;
- }
-
- return m;
- };
-
- moment.parseZone = function () {
- return moment.apply(null, arguments).parseZone();
- };
-
- moment.parseTwoDigitYear = function (input) {
- return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
- };
-
- /************************************
- Moment Prototype
- ************************************/
-
-
- extend(moment.fn = Moment.prototype, {
-
- clone : function () {
- return moment(this);
- },
-
- valueOf : function () {
- return +this._d + ((this._offset || 0) * 60000);
- },
-
- unix : function () {
- return Math.floor(+this / 1000);
- },
-
- 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 m = moment(this).utc();
- if (0 < m.year() && m.year() <= 9999) {
- if ('function' === typeof Date.prototype.toISOString) {
- // native implementation is ~50x faster, use it when we can
- return this.toDate().toISOString();
- } else {
- return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
- }
- } else {
- return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
- }
- },
-
- toArray : function () {
- var m = this;
- return [
- m.year(),
- m.month(),
- m.date(),
- m.hours(),
- m.minutes(),
- m.seconds(),
- m.milliseconds()
- ];
- },
-
- isValid : function () {
- return isValid(this);
- },
-
- isDSTShifted : function () {
- if (this._a) {
- return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
- }
-
- return false;
- },
-
- parsingFlags : function () {
- return extend({}, this._pf);
- },
-
- invalidAt: function () {
- return this._pf.overflow;
- },
-
- utc : function (keepLocalTime) {
- return this.zone(0, keepLocalTime);
- },
-
- local : function (keepLocalTime) {
- if (this._isUTC) {
- this.zone(0, keepLocalTime);
- this._isUTC = false;
-
- if (keepLocalTime) {
- this.add(this._dateTzOffset(), 'm');
- }
- }
- return this;
- },
-
- format : function (inputString) {
- var output = formatMoment(this, inputString || moment.defaultFormat);
- return this.localeData().postformat(output);
- },
-
- add : createAdder(1, 'add'),
-
- subtract : createAdder(-1, 'subtract'),
-
- diff : function (input, units, asFloat) {
- var that = makeAs(input, this),
- zoneDiff = (this.zone() - that.zone()) * 6e4,
- diff, output, daysAdjust;
-
- units = normalizeUnits(units);
-
- if (units === 'year' || units === 'month') {
- // average number of days in the months in the given dates
- diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
- // difference in months
- output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
- // adjust by taking difference in days, average number of days
- // and dst in the given months.
- daysAdjust = (this - moment(this).startOf('month')) -
- (that - moment(that).startOf('month'));
- // same as above but with zones, to negate all dst
- daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) -
- (that.zone() - moment(that).startOf('month').zone())) * 6e4;
- output += daysAdjust / diff;
- if (units === 'year') {
- output = output / 12;
- }
- } else {
- diff = (this - that);
- output = units === 'second' ? diff / 1e3 : // 1000
- units === 'minute' ? diff / 6e4 : // 1000 * 60
- units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
- units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
- units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
- diff;
- }
- return asFloat ? output : absRound(output);
- },
-
- from : function (time, withoutSuffix) {
- return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
- },
-
- fromNow : function (withoutSuffix) {
- return this.from(moment(), withoutSuffix);
- },
-
- calendar : function (time) {
- // We want to compare the start of today, vs this.
- // Getting start-of-today depends on whether we're zone'd or not.
- var now = time || moment(),
- sod = makeAs(now, this).startOf('day'),
- diff = this.diff(sod, 'days', true),
- format = diff < -6 ? 'sameElse' :
- diff < -1 ? 'lastWeek' :
- diff < 0 ? 'lastDay' :
- diff < 1 ? 'sameDay' :
- diff < 2 ? 'nextDay' :
- diff < 7 ? 'nextWeek' : 'sameElse';
- return this.format(this.localeData().calendar(format, this, moment(now)));
- },
-
- isLeapYear : function () {
- return isLeapYear(this.year());
- },
-
- isDST : function () {
- return (this.zone() < this.clone().month(0).zone() ||
- this.zone() < this.clone().month(5).zone());
- },
-
- day : function (input) {
- var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
- if (input != null) {
- input = parseWeekday(input, this.localeData());
- return this.add(input - day, 'd');
- } else {
- return day;
- }
- },
-
- month : makeAccessor('Month', true),
-
- startOf : function (units) {
- units = normalizeUnits(units);
- // the following switch intentionally omits break keywords
- // to utilize falling through the cases.
- switch (units) {
- case 'year':
- this.month(0);
- /* falls through */
- case 'quarter':
- case 'month':
- this.date(1);
- /* falls through */
- case 'week':
- case 'isoWeek':
- case 'day':
- this.hours(0);
- /* falls through */
- case 'hour':
- this.minutes(0);
- /* falls through */
- case 'minute':
- this.seconds(0);
- /* falls through */
- case 'second':
- this.milliseconds(0);
- /* falls through */
- }
-
- // weeks are a special case
- if (units === 'week') {
- this.weekday(0);
- } else if (units === 'isoWeek') {
- this.isoWeekday(1);
- }
-
- // quarters are also special
- if (units === 'quarter') {
- this.month(Math.floor(this.month() / 3) * 3);
- }
-
- return this;
- },
-
- endOf: function (units) {
- units = normalizeUnits(units);
- if (units === undefined || units === 'millisecond') {
- return this;
- }
- return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
- },
-
- isAfter: function (input, units) {
- var inputMs;
- units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this > +input;
- } else {
- inputMs = moment.isMoment(input) ? +input : +moment(input);
- return inputMs < +this.clone().startOf(units);
- }
- },
-
- isBefore: function (input, units) {
- var inputMs;
- units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this < +input;
- } else {
- inputMs = moment.isMoment(input) ? +input : +moment(input);
- return +this.clone().endOf(units) < inputMs;
- }
- },
-
- isSame: function (input, units) {
- var inputMs;
- units = normalizeUnits(units || 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this === +input;
- } else {
- inputMs = +moment(input);
- return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
- }
- },
-
- min: deprecate(
- 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
- function (other) {
- other = moment.apply(null, arguments);
- return other < this ? this : other;
- }
- ),
-
- max: deprecate(
- 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
- function (other) {
- other = moment.apply(null, arguments);
- return other > this ? this : other;
- }
- ),
-
- // keepLocalTime = true means only change the timezone, without
- // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]-->
- // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone
- // +0200, so we adjust the time as needed, to be valid.
- //
- // Keeping the time actually adds/subtracts (one hour)
- // from the actual represented time. That is why we call updateOffset
- // a second time. In case it wants us to change the offset again
- // _changeInProgress == true case, then we have to adjust, because
- // there is no such time in the given timezone.
- zone : function (input, keepLocalTime) {
- var offset = this._offset || 0,
- localAdjust;
- if (input != null) {
- if (typeof input === 'string') {
- input = timezoneMinutesFromString(input);
- }
- if (Math.abs(input) < 16) {
- input = input * 60;
- }
- if (!this._isUTC && keepLocalTime) {
- localAdjust = this._dateTzOffset();
- }
- this._offset = input;
- this._isUTC = true;
- if (localAdjust != null) {
- this.subtract(localAdjust, 'm');
- }
- if (offset !== input) {
- if (!keepLocalTime || this._changeInProgress) {
- addOrSubtractDurationFromMoment(this,
- moment.duration(offset - input, 'm'), 1, false);
- } else if (!this._changeInProgress) {
- this._changeInProgress = true;
- moment.updateOffset(this, true);
- this._changeInProgress = null;
- }
- }
- } else {
- return this._isUTC ? offset : this._dateTzOffset();
- }
- return this;
- },
-
- zoneAbbr : function () {
- return this._isUTC ? 'UTC' : '';
- },
-
- zoneName : function () {
- return this._isUTC ? 'Coordinated Universal Time' : '';
- },
-
- parseZone : function () {
- if (this._tzm) {
- this.zone(this._tzm);
- } else if (typeof this._i === 'string') {
- this.zone(this._i);
- }
- return this;
- },
-
- hasAlignedHourOffset : function (input) {
- if (!input) {
- input = 0;
- }
- else {
- input = moment(input).zone();
- }
-
- return (this.zone() - input) % 60 === 0;
- },
-
- daysInMonth : function () {
- return daysInMonth(this.year(), this.month());
- },
-
- dayOfYear : function (input) {
- var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
- return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
- },
-
- quarter : function (input) {
- return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
- },
-
- weekYear : function (input) {
- var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
- return input == null ? yea
<TRUNCATED>
[18/18] incubator-htrace git commit: HTRACE-174. Refactor GUI
(cmccabe)
Posted by cm...@apache.org.
HTRACE-174. Refactor GUI (cmccabe)
Project: http://git-wip-us.apache.org/repos/asf/incubator-htrace/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-htrace/commit/baaa3a52
Tree: http://git-wip-us.apache.org/repos/asf/incubator-htrace/tree/baaa3a52
Diff: http://git-wip-us.apache.org/repos/asf/incubator-htrace/diff/baaa3a52
Branch: refs/heads/master
Commit: baaa3a5287ac7f096fbbdfc5cbb135050f22aca4
Parents: 4051054
Author: Colin P. Mccabe <cm...@apache.org>
Authored: Tue Jun 9 14:57:12 2015 -0700
Committer: Colin P. Mccabe <cm...@apache.org>
Committed: Tue Jun 9 14:57:12 2015 -0700
----------------------------------------------------------------------
LICENSE.txt | 30 +-
README.md | 2 +-
htrace-htraced/BUILDING.txt | 2 +-
.../src/go/src/org/apache/htrace/common/rest.go | 2 +-
htrace-htraced/src/web/app/about_view.js | 33 +
htrace-htraced/src/web/app/app.js | 20 -
htrace-htraced/src/web/app/modal.js | 34 +
htrace-htraced/src/web/app/models/span.js | 144 -
htrace-htraced/src/web/app/predicate.js | 117 +
htrace-htraced/src/web/app/predicate_view.js | 68 +
htrace-htraced/src/web/app/query_results.js | 45 +
htrace-htraced/src/web/app/router.js | 74 +
htrace-htraced/src/web/app/search_results.js | 25 +
.../src/web/app/search_results_view.js | 365 +
htrace-htraced/src/web/app/search_view.js | 197 +
htrace-htraced/src/web/app/server_info.js | 31 +
htrace-htraced/src/web/app/setup.js | 192 -
htrace-htraced/src/web/app/span.js | 69 +
htrace-htraced/src/web/app/span_details_view.js | 39 +
htrace-htraced/src/web/app/span_widget.js | 229 +
htrace-htraced/src/web/app/string.js | 66 +
htrace-htraced/src/web/app/time_cursor.js | 74 +
htrace-htraced/src/web/app/triangle_button.js | 103 +
.../src/web/app/views/details/details.js | 47 -
htrace-htraced/src/web/app/views/graph/graph.js | 262 -
.../src/web/app/views/search/field.js | 124 -
.../src/web/app/views/search/search.js | 105 -
.../src/web/app/views/swimlane/swimlane.js | 178 -
htrace-htraced/src/web/app/widget_manager.js | 66 +
htrace-htraced/src/web/custom.css | 101 +
htrace-htraced/src/web/index.html | 306 +-
htrace-htraced/src/web/lib/backbone-1.1.2.js | 1608 +++
.../src/web/lib/css/backgrid-0.3.5.min.css | 1 -
.../lib/css/backgrid-paginator-0.3.5.min.css | 1 -
htrace-htraced/src/web/lib/css/main.css | 45 -
htrace-htraced/src/web/lib/jquery-2.1.4.js | 9210 +++++++++++++++++
htrace-htraced/src/web/lib/js/backbone-1.1.2.js | 1608 ---
.../web/lib/js/backbone.marionette-2.4.1.min.js | 23 -
.../src/web/lib/js/backbone.paginator-2.0.2.js | 1325 ---
htrace-htraced/src/web/lib/js/backgrid-0.3.5.js | 2883 ------
.../src/web/lib/js/backgrid-paginator-0.3.5.js | 433 -
htrace-htraced/src/web/lib/js/d3-3.5.5.js | 9504 ------------------
.../src/web/lib/js/jquery-2.1.3.min.js | 4 -
.../src/web/lib/js/moment-2.9.0.min.js | 7 -
.../src/web/lib/js/underscore-1.7.0.js | 1416 ---
htrace-htraced/src/web/lib/moment-2.10.3.js | 3111 ++++++
htrace-htraced/src/web/lib/rome-2.1.0/rome.css | 94 -
htrace-htraced/src/web/lib/rome-2.1.0/rome.js | 4796 ---------
.../src/web/lib/rome-2.1.0/rome.min.css | 2 -
.../src/web/lib/rome-2.1.0/rome.min.js | 3 -
.../src/web/lib/rome-2.1.0/rome.standalone.js | 1860 ----
.../web/lib/rome-2.1.0/rome.standalone.min.js | 2 -
htrace-htraced/src/web/lib/underscore-1.7.0.js | 1416 +++
pom.xml | 9 +-
54 files changed, 17253 insertions(+), 25258 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/LICENSE.txt
----------------------------------------------------------------------
diff --git a/LICENSE.txt b/LICENSE.txt
index 19dd8f7..3404aff 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -244,43 +244,15 @@ backbone, is a javascript library, that is Copyright (c) 2010-2014
Jeremy Ashkenas, DocumentCloud. It is MIT licensed:
https://github.com/jashkenas/backbone/blob/master/LICENSE
-backbone-paginator, is a javascript library, that is Copyright (c) 2012-2014
-Jimmy Yuen Ho Wong and contributors. It is MIT licensed:
-https://github.com/backbone-paginator/backbone.paginator/blob/master/LICENSE-MIT
-
-backgrid, is a javascript library, that is Copyright (c) 2013
-Jimmy Yuen Ho Wong. It is MIT licensed:
-https://github.com/wyuenho/backgrid/blob/master/LICENSE-MIT
-
-backgrid-paginator, is a javascript library, that is Copyright (c) 2013
-Jimmy Yuen Ho Wong. It is MIT licensed:
-https://github.com/wyuenho/backgrid-paginator/blob/master/LICENSE-MIT
-
moment.js is a front end time conversion project.
It is (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors
and shared under the MIT license:
https://github.com/moment/moment/blob/develop/LICENSE
-rome.js is a customizable date (and time) picker.
-It is Copyright © 2014 Nicolas Bevacqua
-https://github.com/bevacqua/rome
-
-Backbone.Wreqr is a message passing system for Backbone.js.
-It is (c) 2012 Derick Bailey, Muted Solutions, LLC and MIT licensed:
-https://github.com/marionettejs/backbone.wreqr/blob/v1.3.1/LICENSE.md
-
-Backbone.Babysitter manages child views for Backbone.js.
-It is (c) 2013 Derick Bailey, Muted Solutions, LLC and MIT licensed:
-https://github.com/marionettejs/backbone.babysitter/blob/v0.1.6/LICENSE.md
-
-Backbone.Marionette is a composite application library for Backbone.js.
-It is MIT licensed:
-https://github.com/marionettejs/backbone.marionette/blob/v2.4.1/license.txt
-
CMP is an implementation of the MessagePack serialization format in
C. It is licensed under the MIT license:
https://github.com/camgunz/cmp/blob/master/LICENSE
go-codec is an implementation of several serialization and deserialization
codecs in Go. It is licensed under the MIT license:
-https://github.com/ugorji/go/blob/master/LICENSE
\ No newline at end of file
+https://github.com/ugorji/go/blob/master/LICENSE
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index b3b486e..d469e22 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,6 @@
HTrace
======
-HTrace is a tracing framework for use with distributed systems written in java.
+HTrace is a tracing framework for use with distributed systems.
See documentation at src/main/site/markdown/index.md or at http://htrace.incubator.apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/BUILDING.txt
----------------------------------------------------------------------
diff --git a/htrace-htraced/BUILDING.txt b/htrace-htraced/BUILDING.txt
index d54d410..abc0113 100644
--- a/htrace-htraced/BUILDING.txt
+++ b/htrace-htraced/BUILDING.txt
@@ -7,7 +7,7 @@ The htrace go code consists of 4 main parts:
* The "htrace" command-line program which can query the server
This is a simple command-line program which can query the htrace server.
-* The htraced Javascript Web UI (not yet implemented)
+* The htraced Javascript Web UI
* The htrace go client library (not yet implemented)
This is the equivalent of the Java HTrace client library, but written in Go.
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/go/src/org/apache/htrace/common/rest.go
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/go/src/org/apache/htrace/common/rest.go b/htrace-htraced/src/go/src/org/apache/htrace/common/rest.go
index eeb9568..b898ca4 100644
--- a/htrace-htraced/src/go/src/org/apache/htrace/common/rest.go
+++ b/htrace-htraced/src/go/src/org/apache/htrace/common/rest.go
@@ -19,7 +19,7 @@
package common
-// Info returned by /serverInfo
+// Info returned by /server/info
type ServerInfo struct {
// The server release version.
ReleaseVersion string
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/about_view.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/about_view.js b/htrace-htraced/src/web/app/about_view.js
new file mode 100644
index 0000000..7dfe868
--- /dev/null
+++ b/htrace-htraced/src/web/app/about_view.js
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+htrace.AboutView = Backbone.View.extend({
+ render: function() {
+ this.$el.html(_.template($("#about-view-template").html())
+ ({ model : this.model }));
+ console.log("AboutView#render");
+ return this;
+ },
+
+ close: function() {
+ console.log("AboutView#close")
+ this.undelegateEvents();
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/app.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/app.js b/htrace-htraced/src/web/app/app.js
deleted file mode 100644
index 0bc7100..0000000
--- a/htrace-htraced/src/web/app/app.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-window.app = new Marionette.Application();
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/modal.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/modal.js b/htrace-htraced/src/web/app/modal.js
new file mode 100644
index 0000000..91d55fe
--- /dev/null
+++ b/htrace-htraced/src/web/app/modal.js
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Show a modal dialog box with a warning message.
+htrace.showModalWarning = function(title, body) {
+ var html = _.template($("#modal-warning-template").html())
+ ({ title: title, body: body });
+ htrace.showModal(html);
+}
+
+// Show a modal dialog box.
+htrace.showModal = function(html) {
+ var el = $("#modal");
+ el.html(html);
+ el.modal();
+}
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/models/span.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/models/span.js b/htrace-htraced/src/web/app/models/span.js
deleted file mode 100644
index b8dc114..0000000
--- a/htrace-htraced/src/web/app/models/span.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Span model
-app.Span = Backbone.Model.extend({
- "defaults": {
- "spanId": null,
- "traceId": null,
- "processId": null,
- "parents": null,
- "description": null,
- "beginTime": 0,
- "stopTime": 0
- },
-
- shorthand: {
- "s": "spanId",
- "b": "beginTime",
- "e": "stopTime",
- "d": "description",
- "r": "processId",
- "p": "parents",
- "i": "traceId"
- },
-
- parse: function(response, options) {
- var attrs = {};
- var $this = this;
- $.each(response, function(key, value) {
- attrs[(key in $this.shorthand) ? $this.shorthand[key] : key] = value;
- });
- return attrs;
- },
-
- duration: function() {
- return this.get('stopTime') - this.get('beginTime');
- }
-});
-
-app.Spans = Backbone.PageableCollection.extend({
- model: app.Span,
- mode: "infinite",
- url: "/query",
- state: {
- pageSize: 10,
- lastSpanId: null,
- finished: false,
- predicates: []
- },
- queryParams: {
- totalPages: null,
- totalRecords: null,
- firstPage: null,
- lastPage: null,
- currentPage: null,
- pageSize: null,
- sortKey: null,
- order: null,
- directions: null,
-
- /**
- * Query parameter for htraced.
- */
- query: function() {
- var predicates = this.state.predicates.slice(0);
- var lastSpanId = this.state.lastSpanId;
-
- /**
- * Use last pulled span ID to paginate.
- * The htraced API works such that order is defined by the first predicate.
- * Adding a predicate to the end of the predicates list won't change the order.
- * Providing the predicate on spanid will filter all previous spanids.
- */
- if (lastSpanId) {
- predicates.push({
- "op": "gt",
- "field": "spanid",
- "val": lastSpanId
- });
- }
-
- return JSON.stringify({
- lim: this.state.pageSize + 1,
- pred: predicates
- });
- }
- },
-
- initialize: function() {
- this.on("reset", function(collection, response, options) {
- if (response.length == 0) {
- delete this.links[this.state.currentPage];
- this.getPreviousPage();
- }
- }, this);
- },
-
- parseLinks: function(resp, xhr) {
- this.state.finished = resp.length <= this.state.pageSize;
-
- if (this.state.finished) {
- this.state.lastSpanId = null;
- } else {
- this.state.lastSpanId = resp[this.state.pageSize - 1].s;
- }
-
- if (this.state.finished) {
- return {};
- }
-
- return {
- "next": "/query?query=" + this.queryParams.query.call(this)
- };
- },
-
- parseRecords: function(resp) {
- return resp.slice(0, 10);
- },
-
- setPredicates: function(predicates) {
- if (!$.isArray(predicates)) {
- console.error("predicates should be an array");
- return;
- }
-
- this.state.predicates = predicates;
- }
-});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/predicate.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/predicate.js b/htrace-htraced/src/web/app/predicate.js
new file mode 100644
index 0000000..87a5602
--- /dev/null
+++ b/htrace-htraced/src/web/app/predicate.js
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.checkStringIsPositiveWholeNumber = function(val) {
+ if (!val.match(/^[0-9]([0-9]*)$/)) {
+ if (!val.match(/[^\s]/)) {
+ throw "You entered an empty string into a numeric field.";
+ }
+ throw "Non-numeric characters found.";
+ }
+};
+
+htrace.checkStringIsNotEmpty = function(val) {
+ if (!val.match(/[^\s]/)) {
+ throw "You entered an empty string into a text field.";
+ }
+};
+
+// Predicate type
+htrace.PType = Backbone.Model.extend({
+ initialize: function(options) {
+ this.name = options.name;
+ this.field = options.field;
+ this.op = options.op;
+ },
+
+ // Try to normalize a value of this type into something htraced can accept.
+ // Returns a string containing the normalized value on success. Throws a
+ // string explaining the parse error otherwise.
+ // Dates are represented by milliseconds since the epoch; span ids don't start
+ // with 0x.
+ normalize: function(val) {
+ switch (this.field) {
+ case "begin":
+ return htrace.parseDate(val).valueOf().toString();
+ case "end":
+ return htrace.parseDate(val).valueOf().toString();
+ case "description":
+ htrace.checkStringIsNotEmpty(val);
+ return val;
+ case "duration":
+ htrace.checkStringIsPositiveWholeNumber(val);
+ return val;
+ case "spanid":
+ return htrace.normalizeSpanId(val);
+ default:
+ return "Normalization not implemented for field '" + this.field + "'";
+ }
+ },
+
+ getDefaultValue: function() {
+ switch (this.field) {
+ case "begin":
+ return htrace.dateToString(moment());
+ case "end":
+ return htrace.dateToString(moment());
+ case "description":
+ return "";
+ case "duration":
+ return "0";
+ case "spanid":
+ return "";
+ default:
+ return "(unknown)";
+ }
+ }
+});
+
+htrace.parsePType = function(name) {
+ switch (name) {
+ case "Began after":
+ return new htrace.PType({name: name, field:"begin", op:"gt"});
+ case "Began at or before":
+ return new htrace.PType({name: name, field:"begin", op:"le"});
+ case "Ended after":
+ return new htrace.PType({name: name, field:"end", op:"gt"});
+ case "Ended at or before":
+ return new htrace.PType({name: name, field:"end", op:"le"});
+ case "Description contains":
+ return new htrace.PType({name: name, field:"description", op:"cn"});
+ case "Description is exactly":
+ return new htrace.PType({name: name, field:"description", op:"eq"});
+ case "Duration is longer than":
+ return new htrace.PType({name: name, field:"duration", op:"gt"});
+ case "Duration is at most":
+ return new htrace.PType({name: name, field:"duration", op:"le"});
+ case "Span ID is":
+ return new htrace.PType({name: name, field:"spanid", op:"eq"});
+ default:
+ return null
+ }
+};
+
+htrace.Predicate = function(options) {
+ this.op = options.ptype.op;
+ this.field = options.ptype.field;
+ this.val = options.val;
+ return this;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/predicate_view.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/predicate_view.js b/htrace-htraced/src/web/app/predicate_view.js
new file mode 100644
index 0000000..aefe896
--- /dev/null
+++ b/htrace-htraced/src/web/app/predicate_view.js
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.PredicateView = Backbone.View.extend({
+ initialize: function(options) {
+ this.el = options.el;
+ this.index = options.index;
+ this.ptype = options.ptype;
+ this.searchView = options.searchView;
+ },
+
+ events: {
+ "click .closeButton": "remove",
+ },
+
+ render: function() {
+ this.$el.html(_.template($("#predicate-template").html())
+ ({ desc: this.ptype.name, id: this.index }))
+ if (this.getText() === "") {
+ $(this.$el).find(".form-control").val(this.ptype.getDefaultValue());
+ }
+ console.log(this.toString() + "#render");
+ return this;
+ },
+
+ // Handle the user removing this predicate.
+ remove: function() {
+ this.searchView.removePredicateView(this);
+ Backbone.View.prototype.remove.apply(this, arguments);
+ },
+
+ // Get the text which the user has entered in.
+ getText: function() {
+ return $(this.$el).find(".form-control").val().trim();
+ },
+
+ // Get the predicate expressed by this view.
+ // Throw an exception if the predicate can't be parsed.
+ getPredicate: function() {
+ return new htrace.Predicate({
+ ptype: this.ptype,
+ val: this.ptype.normalize(this.getText())
+ });
+ },
+
+ toString: function() {
+ return "PredicateView(this.el=" + this.el + ", this.index=" +
+ this.index + ", this.ptype='" + this.ptype.name + "')";
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/query_results.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/query_results.js b/htrace-htraced/src/web/app/query_results.js
new file mode 100644
index 0000000..6fdde9f
--- /dev/null
+++ b/htrace-htraced/src/web/app/query_results.js
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.QueryResults = Backbone.Collection.extend({
+ // The query results are spans.
+ model: htrace.Span,
+
+ initialize: function(options) {
+ this.queryJson = options.queryJson;
+ },
+
+ url: function() {
+ return "query?query=" + this.queryString();
+ },
+
+ parse: function(response, xhr) {
+ return response;
+ },
+
+ prettyQueryString: function() {
+ return JSON.stringify(this.queryJson, null, 2);
+ },
+
+ queryString: function() {
+ return JSON.stringify(this.queryJson);
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/router.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/router.js b/htrace-htraced/src/web/app/router.js
new file mode 100644
index 0000000..607da44
--- /dev/null
+++ b/htrace-htraced/src/web/app/router.js
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.HTraceRouter = Backbone.Router.extend({
+ "routes": {
+ "": "empty",
+ "about": "about",
+ "search": "search",
+ "*unknown": "unknown"
+ },
+
+ empty: function() {
+ console.log("Redirecting to #about.");
+ Backbone.history.navigate("about", {"trigger": true, "replace": true});
+ },
+
+ about: function() {
+ console.log("Visiting #about.");
+ serverInfo = new htrace.ServerInfo();
+ var router = this;
+ serverInfo.fetch({
+ "success": function(model, response, options) {
+ router.switchView(new htrace.AboutView({model: serverInfo, el: "#app"}));
+ router.activateNavBarEntry("about")
+ },
+ "error": function(model, response, options) {
+ window.alert("Failed to fetch htraced server info via GET " +
+ "/server/info: " + JSON.stringify(response));
+ }
+ });
+ },
+
+ search: function() {
+ console.log("Visiting #search.");
+ this.switchView(new htrace.SearchView({el : "#app"}));
+ htrace.router.activateNavBarEntry("search");
+ },
+
+ unknown: function() {
+ console.log("Unknown route " + Backbone.history.getFragment() + ".")
+ },
+
+ "switchView": function(view) {
+ this.view && this.view.close();
+ this.view = view;
+ this.view.render();
+ },
+
+ "activateNavBarEntry": function(id) {
+ $(".nav").find(".active").removeClass("active");
+ $(".nav").find("#" + id).addClass("active");
+ }
+});
+
+htrace.router = new htrace.HTraceRouter();
+Backbone.history.start();
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/search_results.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/search_results.js b/htrace-htraced/src/web/app/search_results.js
new file mode 100644
index 0000000..d214918
--- /dev/null
+++ b/htrace-htraced/src/web/app/search_results.js
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.SearchResults = Backbone.Collection.extend({
+ // The search results are spans.
+ model: htrace.Span
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/search_results_view.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/search_results_view.js b/htrace-htraced/src/web/app/search_results_view.js
new file mode 100644
index 0000000..b3473c4
--- /dev/null
+++ b/htrace-htraced/src/web/app/search_results_view.js
@@ -0,0 +1,365 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.SearchResultsView = Backbone.View.extend({
+ // The minimum time span we will allow between begin and end.
+ MINIMUM_TIME_SPAN: 100,
+
+ begin: 0,
+
+ end: this.MINIMUM_TIME_SPAN,
+
+ focused: false,
+
+ initialize: function(options) {
+ this.model = options.searchResults;
+ this.el = options.el;
+ this.listenTo(this.model, 'add remove change reset', this.render);
+
+ // Re-render the canvas when the window size changes.
+ // Add a debouncer delay to avoid spamming render requests.
+ var view = this;
+ $(window).on("resize", _.debounce(function() {
+ view.render();
+ }, 250));
+ },
+
+ // Get the canvas X coordinate of a mouse click from the absolute event
+ // coordinate.
+ getCanvasX: function(e) {
+ return e.pageX - $("#resultsCanvas").offset().left;
+ },
+
+ // Get the canvas Y coordinate of a mouse click from the absolute event
+ // coordinate.
+ getCanvasY: function(e) {
+ return e.pageY - $("#resultsCanvas").offset().top;
+ },
+
+ handleMouseDown: function(e) {
+ e.preventDefault();
+ var x = this.getCanvasX(e);
+ var y = this.getCanvasY(e);
+ var focused = this.widgetManager.handleMouseDown(x, y);
+ if (focused != this.focused) {
+ this.draw();
+ this.focused = focused;
+ }
+ },
+
+ handleMouseUp: function(e) {
+ e.preventDefault();
+ var x = this.getCanvasX(e);
+ var y = this.getCanvasY(e);
+ this.widgetManager.handleMouseUp(x, y);
+ this.focused = false;
+ this.draw();
+ },
+
+ // When the mouse leaves the canvas, treat it like a mouse up event at -1, -1
+ // if something is focused.
+ handleMouseOut: function(e) {
+ if (this.focused) {
+ this.widgetManager.handleMouseUp(-1, -1);
+ this.focused = false;
+ this.draw();
+ }
+ },
+
+ handleMouseMove: function(e) {
+ e.preventDefault();
+ var x = this.getCanvasX(e);
+ var y = this.getCanvasY(e);
+ if (this.focused) {
+ var mustDraw = false;
+ if (this.widgetManager.handleMouseMove(x, y)) {
+ mustDraw = true;
+ }
+ }
+ if (this.timeCursor.handleMouseMove(x, y)) {
+ mustDraw = true;
+ }
+ if (mustDraw) {
+ this.draw();
+ }
+ },
+
+ render: function() {
+ console.log("SearchResultsView#render.");
+ $(this.el).html(_.template($("#search-results-view-template").html()));
+ $('#selectedTime').attr('readonly', 'readonly');
+ this.canvas = $("#resultsCanvas");
+ this.ctx = this.canvas.get(0).getContext("2d");
+ this.scaleCanvas();
+ this.setupCoordinates();
+ this.setupTimeCursor();
+ this.setupWidgets();
+ this.draw();
+ this.attachEvents();
+ return this;
+ },
+
+ /*
+ * Compute the ratio to use between the size of the canvas (i.e.
+ * canvas.ctx.width, canvas.ctx.height) and the size in "HTML5 pixels." Note
+ * that 'HTML5 pixels" don't actually correspond to screen pixels. A line 1
+ * "HTML5 pixel" wide actually takes up multiple scren pixels, etc.
+ *
+ * TODO: fix this to be sharper
+ */
+ computeScaleFactor: function() {
+ var backingStoreRatio = this.ctx.backingStorePixelRatio ||
+ this.ctx.mozBackingStorePixelRatio ||
+ this.ctx.msBackingStorePixelRatio ||
+ this.ctx.webkitBackingStorePixelRatio ||
+ this.ctx.oBackingStorePixelRatio ||
+ this.ctx.backingStorePixelRatio || 1;
+ return (window.devicePixelRatio || 1) / backingStoreRatio;
+ },
+
+ // Sets up the canvas size and scaling.
+ scaleCanvas: function() {
+ var cssX = this.canvas.parent().innerWidth();
+ var cssY = $(window).innerHeight() - $("#header").innerHeight() - 50;
+ var ratio = this.computeScaleFactor();
+ console.log("scaleCanvas: cssX=" + cssX + ", cssY=" + cssY + ", ratio=" + ratio);
+ this.maxX = cssX;
+ this.maxY = cssY;
+ $('#searchView').css('height', cssY + "px");
+ $('#results').css('width', cssX + "px");
+ $('#results').css('height', cssY + "px");
+ $('#resultsView').css('width', cssX + "px");
+ $('#resultsView').css('height', cssY + "px");
+ $('#resultsDiv').css('width', cssX + "px");
+ $('#resultsDiv').css('height', cssY + "px");
+ $('#resultsCanvas').css('width', cssX + "px");
+ $('#resultsCanvas').css('height', cssY + "px");
+ this.ctx.canvas.width = cssX * ratio;
+ this.ctx.canvas.height = cssY * ratio;
+ this.ctx.scale(ratio, ratio);
+ },
+
+ //
+ // Set up the screen coordinates.
+ //
+ // 0 buttonX descX scrollX maxX
+ // +--------------+----------+--------------------+-----------+
+ // |ProcessId | Buttons | Span Description | Scrollbar |
+ // +--------------+----------+--------------------+-----------+
+ //
+ setupCoordinates: function() {
+ this.buttonX = Math.min(300, Math.floor(this.maxX / 5));
+ this.descX = this.buttonX + Math.min(75, Math.floor(this.maxX / 20));
+ var scrollBarWidth = Math.min(50, Math.floor(this.maxX / 10));
+ this.scrollX = this.maxX - scrollBarWidth;
+ },
+
+ setupTimeCursor: function() {
+ var selectedTime;
+ if (this.timeCursor != null) {
+ selectedTime = this.timeCursor.selectedTime;
+ console.log("setupTimeCursor: selectedTime = (prev) " + selectedTime);
+ } else {
+ selectedTime = this.begin;
+ console.log("setupTimeCursor: selectedTime = (begin) " + selectedTime);
+ }
+ this.timeCursor = new htrace.TimeCursor({
+ ctx: this.ctx,
+ x0: this.descX,
+ xF: this.scrollX,
+ el: "#selectedTime",
+ y0: 0,
+ yF: this.maxY,
+ begin: this.begin,
+ end: this.end,
+ selectedTime: selectedTime
+ });
+ },
+
+ setupWidgets: function() {
+ var widgets = [];
+ var spanWidgetHeight = Math.min(25, Math.floor(this.maxY / 32));
+
+ // Create a SpanWidget for each span we know about
+ var numSpans = this.model.size();
+ for (var i = 0; i < numSpans; i++) {
+ var spanWidget = new htrace.SpanWidget({
+ ctx: this.ctx,
+ span: this.model.at(i),
+ x0: 0,
+ xB: this.buttonX,
+ xD: this.descX,
+ xF: this.scrollX,
+ y0: i * spanWidgetHeight,
+ yF: (i * spanWidgetHeight) + (spanWidgetHeight - 1),
+ begin: this.begin,
+ end: this.end
+ });
+ widgets.push(spanWidget);
+ }
+
+ // Create a new root-leve WidgetManager
+ this.widgetManager = new htrace.WidgetManager({
+ widgets: widgets
+ });
+ },
+
+ draw: function() {
+ if (this.checkCanvasTooSmall()) {
+ return;
+ }
+
+ // Set the background to white.
+ this.ctx.save();
+ this.ctx.fillStyle="#ffffff";
+ this.ctx.strokeStyle="#000000";
+ this.ctx.fillRect(0, 0, this.maxX, this.maxY);
+ this.ctx.restore();
+
+ // Draw all the widgets.
+ this.widgetManager.draw();
+ this.timeCursor.draw();
+ },
+
+ checkCanvasTooSmall: function() {
+ if ((this.maxX < 200) || (this.maxY < 200)) {
+ this.ctx.fillStyle="#cccccc";
+ this.ctx.strokeStyle="#000000";
+ this.ctx.fillRect(0, 0, this.maxX, this.maxY);
+ this.ctx.font = "24px serif";
+ this.ctx.fillStyle="#000000";
+ this.ctx.fillText("Canvas too small!", 0, 24);
+ return true;
+ }
+ return false;
+ },
+
+ attachEvents: function() {
+ // Use jquery to capture mouse events on the canvas.
+ // For some reason using backbone doesn't work for getting these events.
+ var view = this;
+ $("#resultsCanvas").off("mousedown");
+ $("#resultsCanvas").on("mousedown", function(e) {
+ view.handleMouseDown(e);
+ });
+ $("#resultsCanvas").off("mouseup");
+ $("#resultsCanvas").on("mouseup", function(e) {
+ view.handleMouseUp(e);
+ });
+ $("#resultsCanvas").off("mouseout");
+ $("#resultsCanvas").on("mouseout", function(e) {
+ view.handleMouseOut(e);
+ });
+ $(window).off("mouseup");
+ $(window).on("mouseup"), function(e) {
+ view.handleGlobalMouseUp(e);
+ }
+ $("#resultsCanvas").off("mousemove");
+ $("#resultsCanvas").on("mousemove", function(e) {
+ view.handleMouseMove(e);
+ });
+ },
+
+ remove: function() {
+ $(window).off("resize");
+ $("#resultsCanvas").off("mousedown");
+ $("#resultsCanvas").off("mouseup");
+ $("#resultsCanvas").off("mousemove");
+ Backbone.View.prototype.remove.apply(this, arguments);
+ },
+
+ handleBeginOrEndChange: function(e, type) {
+ e.preventDefault();
+ var text = $(e.target).val().trim();
+ var d = null;
+ try {
+ d = htrace.parseDate(text);
+ } catch(err) {
+ $("#begin").val(htrace.dateToString(this.begin));
+ $("#end").val(htrace.dateToString(this.end));
+ htrace.showModalWarning("Timeline " + type + " Format Error",
+ "Please enter a valid time in the timeline " + type + " field.<p/>" +
+ err);
+ return null;
+ }
+ if (type === "begin") {
+ this.setBegin(d.valueOf());
+ } else if (type === "end") {
+ this.setEnd(d.valueOf());
+ } else {
+ throw "invalid type for handleBeginOrEndChange: expected begin or end.";
+ }
+ },
+
+ setBegin: function(val) {
+ if (this.end < val + this.MINIMUM_TIME_SPAN) {
+ this.begin = val;
+ this.end = val + this.MINIMUM_TIME_SPAN;
+ console.log("SearchResultsView#setBegin(begin=" + this.begin +
+ ", end=" + this.end + ")");
+ $("#begin").val(htrace.dateToString(this.begin));
+ $("#end").val(htrace.dateToString(this.end));
+ } else {
+ this.begin = val;
+ console.log("SearchResultsView#setBegin(begin=" + this.begin + ")");
+ $("#begin").val(htrace.dateToString(this.begin));
+ }
+ this.render();
+ },
+
+ setEnd: function(val) {
+ if (this.begin + this.MINIMUM_TIME_SPAN > val) {
+ this.begin = val;
+ this.end = this.begin + this.MINIMUM_TIME_SPAN;
+ console.log("SearchResultsView#setEnd(begin=" + this.begin +
+ ", end=" + this.end + ")");
+ $("#begin").val(htrace.dateToString(this.begin));
+ $("#end").val(htrace.dateToString(this.end));
+ } else {
+ this.end = val;
+ console.log("SearchResultsView#setEnd(end=" + this.end + ")");
+ $("#end").val(htrace.dateToString(this.end));
+ }
+ this.render();
+ },
+
+ zoomFitAll: function() {
+ var numSpans = this.model.size();
+ if (numSpans == 0) {
+ this.setBegin(0);
+ this.setEnd(this.MINIMUM_TIME_SPAN);
+ return;
+ }
+ var minStart = 4503599627370496;
+ var maxEnd = 0;
+ for (var i = 0; i < numSpans; i++) {
+ var span = this.model.at(i);
+ if (span.get('begin') < minStart) {
+ minStart = span.get('begin');
+ }
+ if (span.get('end') > maxEnd) {
+ maxEnd = span.get('end');
+ }
+ }
+ this.setBegin(minStart);
+ this.setEnd(maxEnd);
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/search_view.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/search_view.js b/htrace-htraced/src/web/app/search_view.js
new file mode 100644
index 0000000..52f9101
--- /dev/null
+++ b/htrace-htraced/src/web/app/search_view.js
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+htrace.SearchView = Backbone.View.extend({
+ initialize : function() {
+ this.predicateViews = [];
+ this.highestPredicateIndex = 0;
+ this.searchInProgress = false;
+ this.searchResults = new htrace.SearchResults();
+ this.resultsView = new htrace.SearchResultsView({
+ searchResults: this.searchResults,
+ el: "#results"
+ });
+ },
+
+ events: {
+ "click #searchButton": "searchHandler",
+ "click #clearButton": "clearHandler",
+ "click .add-field": "dropdownHandler",
+ "blur #begin": "blurBeginHandler",
+ "blur #end": "blurEndHandler",
+ "click #zoomButton": "zoomFitAllHandler"
+ },
+
+ searchHandler: function(e){
+ e.preventDefault();
+
+ // Do a new search.
+ this.doSearch(e.ctrlKey);
+ },
+
+ clearHandler: function(e){
+ e.preventDefault();
+
+ // Clear existing search results.
+ this.searchResults.reset();
+ },
+
+ doSearch: function(showDebug){
+ if (this.searchInProgress) {
+ console.log("Can't start a new search while another one is in " +
+ "progress.");
+ return false;
+ }
+
+ // Check if there are no search criteria.
+ if (this.predicateViews.length == 0) {
+ htrace.showModalWarning("No Search Criteria Specified",
+ "You have not specified any search criteria. " +
+ "Use the 'Add Predicate' button to specify what to search for.");
+ return false;
+ }
+
+ // Build the predicate array.
+ predicates = []
+ var predicateViewsLen = this.predicateViews.length;
+ for (var i = 0; i < predicateViewsLen; i++) {
+ var predicateView = this.predicateViews[i];
+ try {
+ predicates.push(predicateView.getPredicate());
+ } catch(err) {
+ htrace.showModalWarning("Search Field Validation Error",
+ "Invalid search string for the '" + predicateView.ptype.name +
+ "' field.<p/>" + err);
+ return false;
+ }
+ }
+ var queryJson = {
+ pred: predicates,
+ lim: 20
+ };
+ // If there are existing search results, we want results which "come after"
+ // those. So pass the last span we saw as a continuation token.
+ if (this.searchResults.size() > 0) {
+ queryJson.prev =
+ this.searchResults.at(this.searchResults.size() - 1).unparse();
+ }
+ var searchView = this;
+ var queryResults = new htrace.QueryResults({queryJson: queryJson});
+ console.log("Starting span query " + queryResults.url());
+ this.searchInProgress = true;
+ queryResults.fetch({
+ success: function(model, response, options){
+ var firstResults = (searchView.searchResults.size() === 0);
+ console.log("Success on span query " + queryResults.url() + ": got " +
+ queryResults.size() + " result(s). firstResults=" + firstResults);
+ searchView.searchResults.add(queryResults.models);
+ if (firstResults) {
+ // After the initial search, zoom to fit everything.
+ // On subsequent searches, we leave the viewport alone.
+ searchView.resultsView.zoomFitAll();
+ }
+ searchView.searchInProgress = false;
+ if (showDebug) {
+ htrace.showModalWarning("Search Debug",
+ "This is the search debug box, accessible by holding down the " +
+ "control key while clicking the search button.<p/>" +
+ "<h3>Query JSON</h3><pre>" + queryResults.prettyQueryString() +
+ "</pre><p/><h3>Response JSON</h3><pre>" +
+ JSON.stringify(queryResults, null, 2) + "</pre><p/>");
+ } else if (queryResults.size() == 0) {
+ if (firstResults) {
+ htrace.showModalWarning("No Results Found",
+ "No results were found for your query.<p/>");
+ } else {
+ htrace.showModalWarning("No Additional Results Found",
+ "No additional results were found for your query.<p/>");
+ }
+ }
+ },
+ error: function(model, response, options){
+ this.searchResults.clear();
+ var err = "Error " + JSON.stringify(response) +
+ " on span query " + query.url();
+ console.log(err);
+ alert(err);
+ searchView.searchInProgress = false;
+ }
+ });
+ return false;
+ },
+
+ dropdownHandler: function(e){
+ e.preventDefault();
+ var text = $(e.target).text();
+ var ptype = htrace.parsePType(text);
+ if (!ptype) {
+ alert("Unable to parse predicate type '" + text + "'");
+ return false;
+ }
+ var index = this.highestPredicateIndex;
+ this.highestPredicateIndex++;
+ var el = "pred" + index;
+ $("#predicates").append('<div id="' + el + '"/></div>');
+ predicateView = new htrace.PredicateView({
+ el: "#" + el,
+ index: index,
+ ptype: ptype,
+ searchView: this
+ });
+ this.predicateViews.push(predicateView);
+ predicateView.render();
+ return true;
+ },
+
+ blurBeginHandler: function(e) {
+ return this.resultsView.handleBeginOrEndChange(e, "begin");
+ },
+
+ blurEndHandler: function(e) {
+ return this.resultsView.handleBeginOrEndChange(e, "end");
+ },
+
+ zoomFitAllHandler: function(e) {
+ e.preventDefault();
+ this.resultsView.zoomFitAll();
+ },
+
+ removePredicateView: function(predicateView) {
+ this.predicateViews = _.without(this.predicateViews, predicateView);
+ },
+
+ render: function() {
+ this.$el.html(_.template($("#search-view-template").html())
+ ({ model : this.model }))
+ this.resultsView.render();
+ console.log("SearchView#render");
+ return this;
+ },
+
+ close: function() {
+ console.log("SearchView#close")
+ while (this.predicateViews.length > 0) {
+ this.predicateViews[0].remove();
+ }
+ this.resultsView.remove();
+ this.resultsView = null;
+ this.undelegateEvents();
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/server_info.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/server_info.js b/htrace-htraced/src/web/app/server_info.js
new file mode 100644
index 0000000..b03f706
--- /dev/null
+++ b/htrace-htraced/src/web/app/server_info.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// htraced ServerInfo sent back from /serverInfo.
+// See rest.go.
+htrace.ServerInfo = Backbone.Model.extend({
+ defaults: {
+ "ReleaseVersion": "unknown",
+ "GitVersion": "unknown",
+ },
+
+ url: function() {
+ return "server/info";
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/setup.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/setup.js b/htrace-htraced/src/web/app/setup.js
deleted file mode 100644
index beb06db..0000000
--- a/htrace-htraced/src/web/app/setup.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-var BaseView = Backbone.Marionette.LayoutView.extend({
- "el": "body",
- "regions": {
- "header": "#header",
- "app": "#app"
- }
-});
-
-var Router = Backbone.Marionette.AppRouter.extend({
- "routes": {
- "": "init",
- "!/search(?:query)": "search",
- "!/spans/:id": "span",
- "!/swimlane/:id": "swimlane",
- "!/swimlane/:id:?:lim": "swimlane"
- },
-
- "initialize": function() {
- // Collection
- this.spansCollection = new app.Spans();
- },
-
- "init": function() {
- Backbone.history.navigate("!/search", {"trigger": true});
- },
-
- "search": function(query) {
- app.root.app.show(new app.SearchView());
-
- var predicates;
-
- this.spansCollection.switchMode("infinite", {
- fetch: false,
- resetState: true
- });
-
- if (query) {
- predicates = _(query.split(";"))
- .map(function(predicate) {
- return _(predicate.split('&'))
- .reduce(function(mem, op) {
- var op = op.split('=');
- mem[op[0]] = op[1];
- return mem;
- }, {});
- });
- this.spansCollection.fullCollection.reset();
- this.spansCollection.setPredicates(predicates);
- }
- else {
- this.spansCollection.fullCollection.reset();
- this.spansCollection.setPredicates([{"op":"cn","field":"description","val":""}]);
- }
- this.spansCollection.fetch();
-
- app.root.app.currentView.controls.show(
- new app.SearchControlsView({
- "collection": this.spansCollection,
- "predicates": predicates
- }));
- app.root.app.currentView.main.show(
- new Backgrid.Grid({
- "collection": this.spansCollection,
- "columns": [{
- "label": "Begin",
- "cell": Backgrid.Cell.extend({
- className: "begin-cell",
- formatter: {
- fromRaw: function(rawData, model) {
- var beginMs = model.get("beginTime")
- return moment(beginMs).format('YYYY/MM/DD HH:mm:ss,SSS');
- },
- toRaw: function(formattedData, model) {
- return formattedData // data entry not supported for this cell
- }
- }
- }),
- "editable": false,
- "sortable": false
- }, {
- "name": "spanId",
- "label": "ID",
- "cell": "string",
- "editable": false,
- "sortable": false
- }, {
- "name": "processId",
- "label": "processId",
- "cell": "string",
- "editable": false,
- "sortable": false
- }, {
- "label": "Duration",
- "cell": Backgrid.Cell.extend({
- className: "duration-cell",
- formatter: {
- fromRaw: function(rawData, model) {
- return model.duration() + " ms"
- },
- toRaw: function(formattedData, model) {
- return formattedData // data entry not supported for this cell
- }
- }
- }),
- "editable": false,
- "sortable": false
- }, {
- "name": "description",
- "label": "Description",
- "cell": "string",
- "editable": false,
- "sortable": false
- }],
- "row": Backgrid.Row.extend({
- "events": {
- "click": "details"
- },
- "details": function() {
- Backbone.history.navigate("!/spans/" + this.model.get("spanId"), {"trigger": true});
- }
- })
- }));
- app.root.app.currentView.pagination.show(
- new Backgrid.Extension.Paginator({
- collection: this.spansCollection,
- }));
- },
-
- "span": function(id) {
- var span = this.spansCollection.findWhere({
- "spanId": id
- });
-
- if (!span) {
- Backbone.history.navigate("!/search", {"trigger": true});
- return;
- }
-
- var graphView = new app.GraphView({
- "collection": this.spansCollection,
- "id": "span-graph"
- });
-
- graphView.on("update:span", function(d) {
- app.root.app.currentView.span.show(
- new app.SpanDetailsView({
- "model": d.span
- }));
- });
-
- app.root.app.show(new app.DetailsView());
- app.root.app.currentView.content.show(graphView);
- app.root.app.currentView.content.currentView.setSpanId(id);
- },
-
- "swimlane": function(id, lim) {
- var top = new app.SwimlaneView();
- app.root.app.show(top);
- top.swimlane.show(new app.SwimlaneGraphView({
- "spanId": id,
- "lim": lim
- }));
- }
-});
-
-app.on("start", function(options) {
- app.root = new BaseView();
- app.routes = new Router();
-
- Backbone.history.start();
-});
-
-app.start();
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/span.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/span.js b/htrace-htraced/src/web/app/span.js
new file mode 100644
index 0000000..2c06fa0
--- /dev/null
+++ b/htrace-htraced/src/web/app/span.js
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// The invalid span ID, which is all zeroes.
+htrace.INVALID_SPAN_ID = "0000000000000000";
+
+htrace.Span = Backbone.Model.extend({
+ // Parse a span sent from htraced.
+ // We use more verbose names for some attributes.
+ // Missing attributes are treated as zero or empty. Numerical attributes are
+ // forced to be numbers.
+ parse: function(response, options) {
+ var span = {};
+ this.set("spanId", response.s ? response.s : htrace.INVALID_SPAN_ID);
+ this.set("traceId", response.i ? response.i : htrace.INVALID_SPAN_ID);
+ this.set("processId", response.r ? response.r : "");
+ this.set("parents", response.p ? response.p : []);
+ this.set("description", response.d ? response.d : "");
+ this.set("begin", response.b ? parseInt(response.b, 10) : 0);
+ this.set("end", response.e ? parseInt(response.e, 10) : 0);
+ return span;
+ },
+
+ // Transform a span model back into a JSON string suitable for sending over
+ // the wire.
+ unparse: function() {
+ var obj = { };
+ if (!(this.get("spanId") === htrace.INVALID_SPAN_ID)) {
+ obj.s = this.get("spanId");
+ }
+ if (!(this.get("traceId") === htrace.INVALID_SPAN_ID)) {
+ obj.i = this.get("traceId");
+ }
+ if (!(this.get("processId") === "")) {
+ obj.r = this.get("processId");
+ }
+ if (this.get("parents").length > 0) {
+ obj.p = this.get("parents");
+ }
+ if (this.get("description").length > 0) {
+ obj.d = this.get("description");
+ }
+ if (this.get("begin") > 0) {
+ obj.b = this.get("begin");
+ }
+ if (this.get("end") > 0) {
+ obj.e = this.get("end");
+ }
+ return obj;
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/span_details_view.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/span_details_view.js b/htrace-htraced/src/web/app/span_details_view.js
new file mode 100644
index 0000000..9a37055
--- /dev/null
+++ b/htrace-htraced/src/web/app/span_details_view.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+htrace.SpanDetailsView = Backbone.View.extend({
+ initialize: function(options) {
+ this.el = options.el;
+ this.model = options.model;
+ }
+
+ render: function() {
+ this.$el.html(_.template($("#about-view-template").html())
+ ({ model : this.model }));
+ console.log("AboutView#render");
+ return this;
+ },
+
+ close: function() {
+ console.log("AboutView#close")
+ this.undelegateEvents();
+ }
+});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/span_widget.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/span_widget.js b/htrace-htraced/src/web/app/span_widget.js
new file mode 100644
index 0000000..f9333d6
--- /dev/null
+++ b/htrace-htraced/src/web/app/span_widget.js
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Widget containing the trace span displayed on the canvas.
+htrace.SpanWidget = function(params) {
+ for (var k in params) {
+ this[k]=params[k];
+ }
+
+ this.selected = false;
+ this.widgetManagerFocused = false;
+ this.xSize = this.xF - this.x0;
+ this.ySize = this.yF - this.y0;
+ this.xDB = this.xD - this.xB;
+
+ var widgets = [];
+ this.upWidget = new htrace.TriangleButton({
+ ctx: this.ctx,
+ direction: "up",
+ x0: this.xB + 2,
+ xF: this.xB + (this.xDB / 2) - 2,
+ y0: this.y0 + 2,
+ yF: this.yF - 2,
+ });
+ widgets.push(this.upWidget);
+ this.downWidget = new htrace.TriangleButton({
+ ctx: this.ctx,
+ direction: "down",
+ x0: this.xB + (this.xDB / 2) + 2,
+ xF: this.xD - 2,
+ y0: this.y0 + 2,
+ yF: this.yF - 2,
+ });
+ widgets.push(this.downWidget);
+ this.widgetManager = new htrace.WidgetManager({
+ widgets: widgets,
+ });
+
+ this.draw = function() {
+ this.drawBackground();
+ this.drawProcessId();
+ this.drawDescription();
+ this.widgetManager.draw();
+ };
+
+ // Draw the background of this span widget.
+ this.drawBackground = function() {
+ this.ctx.save();
+ if (this.selected) {
+ this.ctx.fillStyle="#ffccff";
+ } else {
+ this.ctx.fillStyle="#ffffff";
+ }
+ this.ctx.fillRect(this.x0, this.y0, this.xSize, this.ySize);
+ this.ctx.restore();
+ }
+
+ // Draw process ID text.
+ this.drawProcessId = function() {
+ this.ctx.save();
+ this.ctx.fillStyle="#000000";
+ this.ctx.font = (this.ySize - 2) + "px sans-serif";
+ this.ctx.beginPath();
+ this.ctx.rect(this.x0, this.y0, this.xB - this.x0, this.ySize);
+ this.ctx.clip();
+ this.ctx.fillText(this.span.get('processId'), this.x0, this.yF - 4);
+ this.ctx.restore();
+ };
+
+ // Draw the span description
+ this.drawDescription = function() {
+ // Draw the light blue bar representing time.
+ this.ctx.save();
+ this.ctx.beginPath();
+ this.ctx.rect(this.xD, this.y0, this.xF - this.xD, this.ySize);
+ this.ctx.clip();
+ this.ctx.strokeStyle="#000000";
+ this.ctx.fillStyle="#a7b7ff";
+ var beginX = this.timeToPosition(this.span.get('begin'));
+ var endX = this.timeToPosition(this.span.get('end'));
+
+ // If the span is completely off the screen, draw a diamond at either the
+ // beginning or the end of the bar to indicate whether it's too early or too
+ // late to be seen.
+ if (endX < this.x0) {
+ beginX = this.xD;
+ endX = this.xD;
+ }
+ if (beginX > this.xF) {
+ beginX = this.xF;
+ endX = this.xF;
+ }
+
+ var gapY = 2;
+ var epsilon = Math.max(2, Math.floor(this.xSize / 1000));
+ if (endX - beginX < epsilon) {
+ // The time interval is too narrow to see. Draw a diamond on the point instead.
+ this.ctx.beginPath();
+ this.ctx.moveTo(beginX, this.y0 + gapY);
+ this.ctx.lineTo(beginX + (Math.floor(this.ySize / 2) - gapY),
+ this.y0 + Math.floor(this.ySize / 2));
+ this.ctx.lineTo(beginX, this.yF - gapY);
+ this.ctx.lineTo(beginX - (Math.floor(this.ySize / 2) - gapY),
+ this.y0 + Math.floor(this.ySize / 2));
+ this.ctx.closePath();
+ this.ctx.fill();
+ } else {
+ // Draw a bar from the start time to the end time.
+// console.log("beginX=" + beginX + ", endX=" + endX +
+// ", begin=" + this.span.get('begin') + ", end=" + this.span.get('end'));
+ this.ctx.fillRect(beginX, this.y0 + gapY, endX - beginX,
+ this.ySize - (gapY * 2));
+ }
+
+ // Draw description text
+ this.ctx.fillStyle="#000000";
+ this.ctx.font = (this.ySize - gapY) + "px sans-serif";
+ this.ctx.fillText(this.span.get('description'), this.xD, this.yF - gapY - 2);
+
+ this.ctx.restore();
+ };
+
+ // Convert a time in milliseconds since the epoch to an x position.
+ this.timeToPosition = function(time) {
+ return this.xD +
+ (((time - this.begin) * (this.xF - this.xD)) /
+ (this.end - this.begin));
+ };
+
+ this.inBoundingBox = function(x, y) {
+ return ((x >= this.x0) && (x <= this.xF) && (y >= this.y0) && (y <= this.yF));
+ };
+
+ this.handleMouseDown = function(x, y) {
+ if (!this.inBoundingBox(x, y)) {
+ return false;
+ }
+ if (this.widgetManager.handleMouseDown(x, y)) {
+ this.widgetManagerFocused = true;
+ return true;
+ }
+ this.selected = !this.selected;
+ this.fillSpanDetailsView();
+ return true;
+ };
+
+ this.handleMouseUp = function(x, y) {
+ if (this.widgetManagerFocused) {
+ this.widgetManager.handleMouseUp(x, y);
+ this.widgetManagerFocused = false;
+ }
+ };
+
+ this.handleMouseMove = function(x, y) {
+ if (!this.widgetManagerFocused) {
+ return false;
+ }
+ return this.widgetManager.handleMouseUp(x, y);
+ };
+
+ this.fillSpanDetailsView = function() {
+ var info = {
+ spanID: this.span.get("spanID"),
+ begin: htrace.dateToString(parseInt(this.span.get("begin"), 10)),
+ end: htrace.dateToString(parseInt(this.span.get("end"), 10))
+ };
+ var explicitOrder = {
+ spanId: -3,
+ begin: -2,
+ end: -1
+ };
+ keys = [];
+ for(k in this.span.attributes) {
+ keys.push(k);
+ if (info[k] == null) {
+ info[k] = this.span.get(k);
+ }
+ }
+ // We sort the keys so that the stuff we want at the top appears at the top,
+ // and everything else is in alphabetical order.
+ keys = keys.sort(function(a, b) {
+ var oa = explicitOrder[a] || 0;
+ var ob = explicitOrder[b] || 0;
+ if (oa < ob) {
+ return -1;
+ } else if (oa > ob) {
+ return 1;
+ } else if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+ var len = keys.length;
+ var h = '<table style="table-layout:fixed;width:100%;word-wrap:break-word">';
+ for (i = 0; i < len; i++) {
+ // Make every other row grey to improve visibility.
+ var colorString = ((i%2) == 1) ? "#f1f1f1" : "#ffffff";
+ h += _.template('<tr bgcolor="' + colorString + '">' +
+ '<td style="width:30%;word-wrap:break-word"><%- key %></td>' +
+ '<td style="width:70%;word-wrap:break-word"><%- val %></td>' +
+ "</tr>")({key: keys[i], val: info[keys[i]]});
+ }
+ h += '</table>';
+ $("#spanDetails").html(h);
+ };
+
+ return this;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/string.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/string.js b/htrace-htraced/src/web/app/string.js
new file mode 100644
index 0000000..b0dfb74
--- /dev/null
+++ b/htrace-htraced/src/web/app/string.js
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Parse an ISO8601 date string into a moment.js object.
+htrace.parseDate = function(val) {
+ if (val.match(/^[0-9]([0-9]*)$/)) {
+ // Treat an all-numeric field as UTC milliseconds since the epoch.
+ return moment.utc(parseInt(val, 10));
+ }
+ // Look for approved date formats.
+ var toTry = [
+ "YYYY-MM-DDTHH:mm:ss,SSS",
+ "YYYY-MM-DDTHH:mm:ss",
+ "YYYY-MM-DDTHH:mm",
+ "YYYY-MM-DD"
+ ];
+ for (var i = 0; i < toTry.length; i++) {
+ var m = moment.utc(val, toTry[i], true);
+ if (m.isValid()) {
+ return m;
+ }
+ }
+ throw "Please enter the date either as YYYY-MM-DDTHH:mm:ss,SSS " +
+ "in UTC, or as the number of milliseconds since the epoch.";
+};
+
+// Convert a moment.js moment into an ISO8601-style date string.
+htrace.dateToString = function(val) {
+ return moment.utc(val).format("YYYY-MM-DDTHH:mm:ss,SSS");
+};
+
+// Normalize a span ID into the format the server expects to see
+// (no leading 0x).
+htrace.normalizeSpanId = function(str) {
+ // Strip off the 0x prefix, if there is one.
+ if (str.indexOf("0x") == 0) {
+ str = str.substring(2);
+ }
+ if (str.length != 16) {
+ throw "The length of '" + str + "' was " + str.length +
+ ", but span IDs must be 16 characters long.";
+ }
+ if (str.search(/[^0-9a-fA-F]/) != -1) {
+ throw "Span IDs must contain only hexadecimal digits, but '" + str +
+ "' contained invalid characters.";
+ }
+ return str;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/time_cursor.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/time_cursor.js b/htrace-htraced/src/web/app/time_cursor.js
new file mode 100644
index 0000000..0060abb
--- /dev/null
+++ b/htrace-htraced/src/web/app/time_cursor.js
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Draws a vertical bar selecting a time.
+htrace.TimeCursor = function(params) {
+ this.selectedTime = -1;
+ for (var k in params) {
+ this[k]=params[k];
+ }
+
+ this.positionToTime = function(x) {
+ if ((x < this.x0) || (x > this.xF)) {
+ return -1;
+ }
+ return this.begin +
+ (((x - this.x0) * (this.end - this.begin)) / (this.xF - this.x0));
+ };
+
+ this.timeToPosition = function(time) {
+ return this.x0 + (((time - this.begin) *
+ (this.xF - this.x0)) / (this.end - this.begin));
+ };
+
+ this.draw = function() {
+ if (this.selectedTime != -1) {
+ this.ctx.save();
+ this.ctx.beginPath();
+ this.ctx.rect(this.x0, this.y0,
+ this.xF - this.x0, this.yF - this.y0);
+ this.ctx.clip();
+ this.ctx.strokeStyle="#ff0000";
+ var x = this.timeToPosition(this.selectedTime);
+ this.ctx.beginPath();
+ this.ctx.moveTo(x, this.y0);
+ this.ctx.lineTo(x, this.yF);
+ this.ctx.stroke();
+ this.ctx.restore();
+ }
+ };
+
+ this.handleMouseMove = function(x, y) {
+ if ((y >= this.y0) && (y <= this.yF) &&
+ (x >= this.x0) && (x <= this.xF)) {
+ this.selectedTime = this.positionToTime(x);
+ if (this.selectedTime < 0) {
+ $(this.el).val("");
+ } else {
+ $(this.el).val(htrace.dateToString(this.selectedTime));
+ }
+ return true;
+ }
+ return false;
+ };
+
+ return this;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/triangle_button.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/triangle_button.js b/htrace-htraced/src/web/app/triangle_button.js
new file mode 100644
index 0000000..89f9514
--- /dev/null
+++ b/htrace-htraced/src/web/app/triangle_button.js
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Triangle button widget.
+htrace.TriangleButton = function(params) {
+ this.fgColor = "#6600ff";
+ this.bgColor = "#ffffff";
+ this.selected = false;
+ this.direction = "down";
+
+ this.draw = function() {
+ this.ctx.save();
+ var fg = this.selected ? this.bgColor : this.fgColor;
+ var bg = this.selected ? this.fgColor : this.bgColor;
+ this.ctx.beginPath();
+ this.ctx.rect(this.x0, this.y0,
+ this.xF - this.x0, this.yF - this.y0);
+ this.ctx.clip();
+ this.ctx.fillStyle = bg;
+ this.ctx.strokeStyle = fg;
+ this.ctx.fillRect(this.x0, this.y0,
+ this.xF - this.x0, this.yF - this.y0);
+ this.ctx.lineWidth = 3;
+ this.ctx.strokeRect(this.x0, this.y0,
+ this.xF - this.x0, this.yF - this.y0);
+ var xPad = (this.xF - this.x0) / 5;
+ var yPad = (this.yF - this.y0) / 5;
+ this.ctx.fillStyle = fg;
+ this.ctx.strokeStyle = fg;
+ this.ctx.beginPath();
+ this.ctx.strokeStyle = fg;
+ if (this.direction === "up") {
+ this.ctx.moveTo(Math.floor(this.x0 + ((this.xF - this.x0) / 2)),
+ this.y0 + yPad);
+ this.ctx.lineTo(this.xF - xPad, this.yF - yPad);
+ this.ctx.lineTo(this.x0 + xPad, this.yF - yPad);
+ } else if (this.direction === "down") {
+ this.ctx.moveTo(this.x0 + xPad, this.y0 + yPad);
+ this.ctx.lineTo(this.xF - xPad, this.y0 + yPad);
+ this.ctx.lineTo(Math.floor(this.x0 + ((this.xF - this.x0) / 2)),
+ this.yF - yPad);
+ } else {
+ console.log("TriangleButton: unknown direction " + this.direction);
+ }
+ this.ctx.closePath();
+ this.ctx.fill();
+ this.ctx.restore();
+ };
+
+ this.inBoundingBox = function(x, y) {
+ return ((x >= this.x0) && (x <= this.xF) && (y >= this.y0) && (y <= this.yF));
+ }
+
+ this.handleMouseDown = function(x, y) {
+// console.log("TriangleButton#handleMouseDown(x=" + x + ", y=" + y +
+// ", x0=" + this.x0 + ", y0="+ this.y0 +
+// ", xF=" + this.xF + ", yF=" + this.yF);
+ if (this.inBoundingBox(x,y)) {
+ this.selected = true;
+ return true;
+ }
+ return false;
+ }
+
+ this.handleMouseUp = function(x, y) {
+ if (this.selected) {
+ console.log("executing callback");
+ }
+ this.selected = false;
+ }
+
+ this.handleMouseMove = function(x, y) {
+ var selected = this.inBoundingBox(x,y);
+ if (this.selected != selected) {
+ this.selected = selected;
+ return true;
+ }
+ return false;
+ }
+
+ for (var k in params) {
+ this[k]=params[k];
+ }
+ return this;
+};
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/views/details/details.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/views/details/details.js b/htrace-htraced/src/web/app/views/details/details.js
deleted file mode 100644
index 2f79e1b..0000000
--- a/htrace-htraced/src/web/app/views/details/details.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-app.DetailsView = Backbone.Marionette.LayoutView.extend({
- "template": "#details-layout-template",
- "regions": {
- "span": "div[role='complementary']",
- "content": "div[role='main']"
- }
-});
-
-app.SpanDetailsView = Backbone.Marionette.ItemView.extend({
- "className": "span",
- "template": "#span-details-template",
-
- "serializeData": function() {
- var context = {
- "span": this.model.toJSON()
- };
- context["span"]["duration"] = this.model.duration();
- return context;
- },
-
- "events": {
- "click": "swimlane"
- },
- "swimlane": function() {
- Backbone.history.navigate("!/swimlane/" + this.model.get("spanId"),
- {"trigger": true});
- }
-});
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/baaa3a52/htrace-htraced/src/web/app/views/graph/graph.js
----------------------------------------------------------------------
diff --git a/htrace-htraced/src/web/app/views/graph/graph.js b/htrace-htraced/src/web/app/views/graph/graph.js
deleted file mode 100644
index 7b4f89e..0000000
--- a/htrace-htraced/src/web/app/views/graph/graph.js
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-app.GraphView = Backbone.View.extend({
- initialize: function(options) {
- options = options || {};
-
- if (!options.id) {
- console.error("GraphView requires argument 'id' to uniquely identify this graph.");
- return;
- }
-
- _.bindAll(this, "render");
- this.collection.bind('change', this.render);
-
- var links = this.links = [];
- var linkTable = this.linkTable = {};
- var nodes = this.nodes = [];
- var nodeTable = this.nodeTable = {};
- var force = this.force
- = d3.layout.force().size([$(window).width(), $(window).height() * 3/4])
- .linkDistance($(window).height() / 5)
- .charge(-120)
- .gravity(0)
- ;
- force.nodes(nodes)
- .links(links);
-
- force.on("tick", function(e) {
- var root = d3.select("#" + options.id);
-
- if (!root.node()) {
- return;
- }
-
- var selectedDatum = root.select(".selected").datum();
-
- // center selected node
- root.select("svg").attr("width", $(root.node()).width());
- selectedDatum.x = root.select("svg").attr("width") / 2;
- selectedDatum.y = root.select("svg").attr("height") / 2;
-
- // Push sources up and targets down to form a weak tree.
- var k = 10 * e.alpha;
- force.links().forEach(function(d, i) {
- d.source.y -= k;
- d.target.y += k;
- });
-
- var nodes = root.selectAll(".node").data(force.nodes());
- nodes.select("circle")
- .attr("cx", function(d) { return d.x; })
- .attr("cy", function(d) { return d.y; });
- nodes.select("text")
- .attr("x", function(d) { return d.x - this.getComputedTextLength() / 2; })
- .attr("y", function(d) { return d.y; });
- root.selectAll(".link").data(force.links())
- .attr("d", function(d) {
- var start = {},
- end = {},
- angle = Math.atan2((d.target.x - d.source.x), (d.target.y - d.source.y));
- start.x = d.source.x + d.source.r * Math.sin(angle);
- end.x = d.target.x - d.source.r * Math.sin(angle);
- start.y = d.source.y + d.source.r * Math.cos(angle);
- end.y = d.target.y - d.source.r * Math.cos(angle);
- return "M" + start.x + " " + start.y
- + " L" + end.x + " " + end.y;
- });
- });
- },
-
- updateLinksAndNodes: function() {
- if (!this.spanId) {
- return;
- }
-
- var $this = this, collection = this.collection;
-
- var selectedSpan = this.collection.findWhere({
- "spanId": this.spanId
- });
-
- var findChildren = function(span) {
- var spanId = span.get("spanId");
- var spans = collection.filter(function(model) {
- return _(model.get("parents")).contains(spanId);
- });
- return _(spans).reject(function(span) {
- return span == null;
- });
- };
- var findParents = function(span) {
- var spans = _(span.get("parents")).map(function(parentSpanId) {
- return collection.findWhere({
- "spanId": parentSpanId
- });
- });
- return _(spans).reject(function(span) {
- return span == null;
- });
- };
- var spanToNode = function(span, level) {
- var table = $this.nodeTable;
- if (!(span.get("spanId") in table)) {
- table[span.get("spanId")] = {
- "name": span.get("spanId"),
- "span": span,
- "level": level,
- "group": 0,
- "x": parseInt($this.svg.attr('width')) / 2,
- "y": 250 + level * 50
- };
- $this.nodes.push(table[span.get("spanId")]);
- }
-
- return table[span.get("spanId")];
- };
- var createLink = function(source, target) {
- var table = $this.linkTable;
- var name = source.span.get("spanId") + "-" + target.span.get("spanId");
- if (!(name in table)) {
- table[name] = {
- "source": source,
- "target": target
- };
- $this.links.push(table[name]);
- }
-
- return table[name];
- };
-
- var parents = [], children = [];
- var selectedSpanNode = spanToNode(selectedSpan, 1);
-
- Array.prototype.push.apply(parents, findParents(selectedSpan));
- _(parents).each(function(span) {
- Array.prototype.push.apply(parents, findParents(span));
- createLink(spanToNode(span, 0), selectedSpanNode)
- });
-
- Array.prototype.push.apply(children, findChildren(selectedSpan));
- _(children).each(function(span) {
- Array.prototype.push.apply(children, findChildren(span));
- createLink(selectedSpanNode, spanToNode(span, 2))
- });
- },
-
- renderLinks: function(selection) {
- var path = selection.enter().append("path")
- .classed("link", true)
- .style("marker-end", "url(#suit)");
- selection.exit().remove();
- return selection;
- },
-
- renderNodes: function(selection) {
- var $this = this;
- var g = selection.enter().append("g").attr("class", "node");
- var circle = g.append("circle")
- .attr("r", function(d) {
- if (!d.radius) {
- d.r = Math.log(d.span.duration());
-
- if (d.r > app.GraphView.MAX_NODE_SIZE) {
- d.r = app.GraphView.MAX_NODE_SIZE;
- }
-
- if (d.r < app.GraphView.MIN_NODE_SIZE) {
- d.r = app.GraphView.MIN_NODE_SIZE;
- }
- }
-
- return d.r;
- });
- var text = g.append("text").text(function(d) {
- return d.span.get("description");
- });
-
- selection.exit().remove();
-
- circle.on("click", function(d) {
- $this.setSpanId(d.name);
- });
-
- selection.classed("selected", null);
- selection.filter(function(d) {
- return d.span.get("spanId") == $this.spanId;
- }).classed("selected", true);
-
- return selection;
- },
-
- setSpanId: function(spanId) {
- var $this = this;
- this.spanId = spanId;
-
- this.updateLinksAndNodes();
-
- this.renderNodes(
- this.svg.selectAll(".node")
- .data(this.force.nodes(), function(d) {
- return d.name;
- }));
-
- this.renderLinks(
- this.svg.selectAll(".link")
- .data(this.force.links(), function(d) {
- return d.source.name + "-" + d.target.name;
- }));
-
- this.force.start();
-
- Backbone.history.navigate("!/spans/" + spanId);
- this.trigger("update:span", {"span": this.collection.findWhere({
- "spanId": spanId
- })});
- },
-
- render: function() {
- this.svg = d3.select(this.$el[0]).append("svg");
- this.svg.attr("height", 500)
- .attr("width", $(window).width())
- .attr("id", this.id);
-
- // Arrows
- this.svg.append("defs").selectAll("marker")
- .data(["suit", "licensing", "resolved"])
- .enter().append("marker")
- .attr("id", function(d) { return d; })
- .attr("viewBox", "0 -5 10 10")
- .attr("refX", 25)
- .attr("refY", 0)
- .attr("markerWidth", 6)
- .attr("markerHeight", 6)
- .attr("orient", "auto")
- .append("path")
- .attr("d", "M0,-5L10,0L0,5 L10,0 L0, -5")
- .style("stroke", "#4679BD")
- .style("opacity", "0.6");
-
- return this;
- }
-});
-
-app.GraphView.MAX_NODE_SIZE = 150;
-app.GraphView.MIN_NODE_SIZE = 50;