{"version":3,"file":"ig.publicmaps.application.min.js","sources":["ig.publicmaps.application.js"],"sourcesContent":["/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */\n!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) {\r\n 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.1\", 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: function (a) { return !n.isArray(a) && a - parseFloat(a) >= 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) { var 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\" + -new Date, v = a.document, w = 0, x = 0, y = gb(), z = gb(), A = gb(), B = function (a, b) { return a === b && (l = !0), 0 }, C = \"undefined\", D = 1 << 31, E = {}.hasOwnProperty, F = [], G = F.pop, H = F.push, I = F.push, J = F.slice, K = F.indexOf || function (a) { for (var b = 0, c = this.length; c > b; b++) if (this[b] === a) return b; return -1 }, L = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\", M = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\", N = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\", O = N.replace(\"w\", \"w#\"), P = \"\\\\[\" + M + \"*(\" + N + \")(?:\" + M + \"*([*^$|!~]?=)\" + M + \"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + O + \"))|)\" + M + \"*\\\\]\", Q = \":(\" + N + \")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + P + \")*)|.*)\\\\)|)\", R = new RegExp(\"^\" + M + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + M + \"+$\", \"g\"), S = new RegExp(\"^\" + M + \"*,\" + M + \"*\"), T = new RegExp(\"^\" + M + \"*([>+~]|\" + M + \")\" + M + \"*\"), U = new RegExp(\"=\" + M + \"*([^\\\\]'\\\"]*?)\" + M + \"*\\\\]\", \"g\"), V = new RegExp(Q), W = new RegExp(\"^\" + O + \"$\"), X = { ID: new RegExp(\"^#(\" + N + \")\"), CLASS: new RegExp(\"^\\\\.(\" + N + \")\"), TAG: new RegExp(\"^(\" + N.replace(\"w\", \"w*\") + \")\"), ATTR: new RegExp(\"^\" + P), PSEUDO: new RegExp(\"^\" + Q), CHILD: new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + M + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + M + \"*(?:([+-]|)\" + M + \"*(\\\\d+)|))\" + M + \"*\\\\)|)\", \"i\"), bool: new RegExp(\"^(?:\" + L + \")$\", \"i\"), needsContext: new RegExp(\"^\" + M + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + M + \"*((?:-\\\\d)?\\\\d*)\" + M + \"*\\\\)|)(?=[^-]|$)\", \"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}\" + M + \"?|(\" + M + \")|.)\", \"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) }; try { I.apply(F = J.call(v.childNodes), v.childNodes), F[v.childNodes.length].nodeType } catch (eb) { I = { apply: F.length ? function (a, b) { H.apply(a, J.call(b)) } : function (a, b) { var c = a.length, d = 0; while (a[c++] = b[d++]); a.length = c - 1 } } } function fb(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 || [], !a || \"string\" != typeof a) return d; if (1 !== (k = b.nodeType) && 9 !== k) return []; if (p && !e) { if (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 I.apply(d, b.getElementsByTagName(a)), d; if ((j = f[3]) && c.getElementsByClassName && b.getElementsByClassName) return I.apply(d, b.getElementsByClassName(j)), d } if (c.qsa && (!q || !q.test(a))) { if (s = r = u, w = b, x = 9 === 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 + qb(o[l]); w = ab.test(a) && ob(b.parentNode) || b, x = o.join(\",\") } if (x) try { return I.apply(d, w.querySelectorAll(x)), d } catch (y) { } finally { r || b.removeAttribute(\"id\") } } } return i(a.replace(R, \"$1\"), b, d, e) } function gb() { var a = []; function b(c, e) { return a.push(c + \" \") > d.cacheLength && delete b[a.shift()], b[c + \" \"] = e } return b } function hb(a) { return a[u] = !0, a } function ib(a) { var b = n.createElement(\"div\"); try { return !!a(b) } catch (c) { return !1 } finally { b.parentNode && b.parentNode.removeChild(b), b = null } } function jb(a, b) { var c = a.split(\"|\"), e = a.length; while (e--) d.attrHandle[c[e]] = b } function kb(a, b) { var c = b && a, d = c && 1 === a.nodeType && 1 === b.nodeType && (~b.sourceIndex || D) - (~a.sourceIndex || D); if (d) return d; if (c) while (c = c.nextSibling) if (c === b) return -1; return a ? 1 : -1 } function lb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return \"input\" === c && b.type === a } } function mb(a) { return function (b) { var c = b.nodeName.toLowerCase(); return (\"input\" === c || \"button\" === c) && b.type === a } } function nb(a) { return hb(function (b) { return b = +b, hb(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 ob(a) { return a && typeof a.getElementsByTagName !== C && a } c = fb.support = {}, f = fb.isXML = function (a) { var b = a && (a.ownerDocument || a).documentElement; return b ? \"HTML\" !== b.nodeName : !1 }, m = fb.setDocument = function (a) { var b, e = a ? a.ownerDocument || a : v, g = e.defaultView; return e !== n && 9 === e.nodeType && e.documentElement ? (n = e, o = e.documentElement, p = !f(e), g && g !== g.top && (g.addEventListener ? g.addEventListener(\"unload\", function () { m() }, !1) : g.attachEvent && g.attachEvent(\"onunload\", function () { m() })), c.attributes = ib(function (a) { return a.className = \"i\", !a.getAttribute(\"className\") }), c.getElementsByTagName = ib(function (a) { return a.appendChild(e.createComment(\"\")), !a.getElementsByTagName(\"*\").length }), c.getElementsByClassName = $.test(e.getElementsByClassName) && ib(function (a) { return a.innerHTML = \"
\", a.firstChild.className = \"i\", 2 === a.getElementsByClassName(\"i\").length }), c.getById = ib(function (a) { return o.appendChild(a).id = u, !e.getElementsByName || !e.getElementsByName(u).length }), c.getById ? (d.find.ID = function (a, b) { if (typeof b.getElementById !== C && p) { var c = b.getElementById(a); return c && c.parentNode ? [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 = typeof a.getAttributeNode !== C && a.getAttributeNode(\"id\"); return c && c.value === b } }), d.find.TAG = c.getElementsByTagName ? function (a, b) { return typeof b.getElementsByTagName !== C ? b.getElementsByTagName(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 typeof b.getElementsByClassName !== C && p ? b.getElementsByClassName(a) : void 0 }, r = [], q = [], (c.qsa = $.test(e.querySelectorAll)) && (ib(function (a) { a.innerHTML = \"\", a.querySelectorAll(\"[msallowclip^='']\").length && q.push(\"[*^$]=\" + M + \"*(?:''|\\\"\\\")\"), a.querySelectorAll(\"[selected]\").length || q.push(\"\\\\[\" + M + \"*(?:value|\" + L + \")\"), a.querySelectorAll(\":checked\").length || q.push(\":checked\") }), ib(function (a) { var b = e.createElement(\"input\"); b.setAttribute(\"type\", \"hidden\"), a.appendChild(b).setAttribute(\"name\", \"D\"), a.querySelectorAll(\"[name=d]\").length && q.push(\"name\" + M + \"*[*^$|!~]?=\"), 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)) && ib(function (a) { c.disconnectedMatch = s.call(a, \"div\"), s.call(a, \"[s!='']:x\"), r.push(\"!=\", Q) }), 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 === e || a.ownerDocument === v && t(v, a) ? -1 : b === e || b.ownerDocument === v && t(v, b) ? 1 : k ? K.call(k, a) - K.call(k, b) : 0 : 4 & d ? -1 : 1) } : function (a, b) { if (a === b) return l = !0, 0; var c, d = 0, f = a.parentNode, g = b.parentNode, h = [a], i = [b]; if (!f || !g) return a === e ? -1 : b === e ? 1 : f ? -1 : g ? 1 : k ? K.call(k, a) - K.call(k, b) : 0; if (f === g) return kb(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 ? kb(h[d], i[d]) : h[d] === v ? -1 : i[d] === v ? 1 : 0 }, e) : n }, fb.matches = function (a, b) { return fb(a, null, null, b) }, fb.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 fb(b, n, null, [a]).length > 0 }, fb.contains = function (a, b) { return (a.ownerDocument || a) !== n && m(a), t(a, b) }, fb.attr = function (a, b) { (a.ownerDocument || a) !== n && m(a); var e = d.attrHandle[b.toLowerCase()], f = e && E.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 }, fb.error = function (a) { throw new Error(\"Syntax error, unrecognized expression: \" + a) }, fb.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 = fb.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 = fb.selectors = { cacheLength: 50, createPseudo: hb, 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] || fb.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] && fb.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(\"(^|\" + M + \")\" + a + \"(\" + M + \"|$)\")) && y(a, function (a) { return b.test(\"string\" == typeof a.className && a.className || typeof a.getAttribute !== C && a.getAttribute(\"class\") || \"\") }) }, ATTR: function (a, b, c) { return function (d) { var e = fb.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 + \" \").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()] || fb.error(\"unsupported pseudo: \" + a); return e[u] ? e(b) : e.length > 1 ? (c = [a, a, \"\", b], d.setFilters.hasOwnProperty(a.toLowerCase()) ? hb(function (a, c) { var d, f = e(a, b), g = f.length; while (g--) d = K.call(a, f[g]), a[d] = !(c[d] = f[g]) }) : function (a) { return e(a, 0, c) }) : e } }, pseudos: { not: hb(function (a) { var b = [], c = [], d = h(a.replace(R, \"$1\")); return d[u] ? hb(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), !c.pop() } }), has: hb(function (a) { return function (b) { return fb(a, b).length > 0 } }), contains: hb(function (a) { return function (b) { return (b.textContent || b.innerText || e(b)).indexOf(a) > -1 } }), lang: hb(function (a) { return W.test(a || \"\") || fb.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) return !1; return !0 }, parent: function (a) { return !d.pseudos.empty(a) }, header: function (a) { return Z.test(a.nodeName) }, input: function (a) { return Y.test(a.nodeName) }, button: function (a) { var b = a.nodeName.toLowerCase(); return \"input\" === b && \"button\" === a.type || \"button\" === b }, text: function (a) { var b; return \"input\" === a.nodeName.toLowerCase() && \"text\" === a.type && (null == (b = a.getAttribute(\"type\")) || \"text\" === b.toLowerCase()) }, first: nb(function () { return [0] }), last: nb(function (a, b) { return [b - 1] }), eq: nb(function (a, b, c) { return [0 > c ? c + b : c] }), even: nb(function (a, b) { for (var c = 0; b > c; c += 2) a.push(c); return a }), odd: nb(function (a, b) { for (var c = 1; b > c; c += 2) a.push(c); return a }), lt: nb(function (a, b, c) { for (var d = 0 > c ? c + b : c; --d >= 0;) a.push(d); return a }), gt: nb(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] = lb(b); for (b in { submit: !0, reset: !0 }) d.pseudos[b] = mb(b); function pb() { } pb.prototype = d.filters = d.pseudos, d.setFilters = new pb, g = fb.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 ? fb.error(a) : z(a, i).slice(0) }; function qb(a) { for (var b = 0, c = a.length, d = \"\"; c > b; b++) d += a[b].value; return d } function rb(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 sb(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 tb(a, b, c) { for (var d = 0, e = b.length; e > d; d++) fb(a, b[d], c); return c } function ub(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 vb(a, b, c, d, e, f) { return d && !d[u] && (d = vb(d)), e && !e[u] && (e = vb(e, f)), hb(function (f, g, h, i) { var j, k, l, m = [], n = [], o = g.length, p = f || tb(b || \"*\", h.nodeType ? [h] : h, []), q = !a || !f && b ? p : ub(p, m, a, h, i), r = c ? e || (f ? a : o || d) ? [] : g : q; if (c && c(q, r, h, i), d) { j = ub(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 ? K.call(f, l) : m[k]) > -1 && (f[j] = !(g[j] = l)) } } else r = ub(r === g ? r.splice(o, r.length) : r), e ? e(null, g, r, i) : I.apply(g, r) }) } function wb(a) { for (var b, c, e, f = a.length, g = d.relative[a[0].type], h = g || d.relative[\" \"], i = g ? 1 : 0, k = rb(function (a) { return a === b }, h, !0), l = rb(function (a) { return K.call(b, a) > -1 }, h, !0), m = [function (a, c, d) { return !g && (d || c !== j) || ((b = c).nodeType ? k(a, c, d) : l(a, c, d)) }]; f > i; i++) if (c = d.relative[a[i].type]) m = [rb(sb(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 vb(i > 1 && sb(m), i > 1 && qb(a.slice(0, i - 1).concat({ value: \" \" === a[i - 2].type ? \"*\" : \"\" })).replace(R, \"$1\"), c, e > i && wb(a.slice(i, e)), f > e && wb(a = a.slice(e)), f > e && qb(a)) } m.push(c) } return sb(m) } function xb(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] = G.call(i)); s = ub(s) } I.apply(i, s), k && !f && s.length > 0 && p + b.length > 1 && fb.uniqueSort(i) } return k && (w = v, j = t), r }; return c ? hb(f) : f } return h = fb.compile = function (a, b) { var c, d = [], e = [], f = A[a + \" \"]; if (!f) { b || (b = g(a)), c = b.length; while (c--) f = wb(b[c]), f[u] ? d.push(f) : e.push(f); f = A(a, xb(e, d)), f.selector = a } return f }, i = fb.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) && ob(b.parentNode) || b))) { if (j.splice(i, 1), a = f.length && qb(j), !a) return I.apply(e, f), e; break } } } return (n || h(a, o))(f, b, !p, e, ab.test(a) && ob(b.parentNode) || b), e }, c.sortStable = u.split(\"\").sort(B).join(\"\") === u, c.detectDuplicates = !!l, m(), c.sortDetached = ib(function (a) { return 1 & a.compareDocumentPosition(n.createElement(\"div\")) }), ib(function (a) { return a.innerHTML = \"\", \"#\" === a.firstChild.getAttribute(\"href\") }) || jb(\"type|href|height|width\", function (a, b, c) { return c ? void 0 : a.getAttribute(b, \"type\" === b.toLowerCase() ? 1 : 2) }), c.attributes && ib(function (a) { return a.innerHTML = \"\", a.firstChild.setAttribute(\"value\", \"\"), \"\" === a.firstChild.getAttribute(\"value\") }) || jb(\"value\", function (a, b, c) { return c || \"input\" !== a.nodeName.toLowerCase() ? void 0 : a.defaultValue }), ib(function (a) { return null == a.getAttribute(\"disabled\") }) || jb(L, function (a, b, c) { var d; return c ? void 0 : a[b] === !0 ? b.toLowerCase() : (d = a.getAttributeNode(b)) && d.specified ? d.value : null }), fb }(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.jquery ? (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; return 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, \"nextSibling\") }, 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\"), \"resolved\"], [\"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 + Math.random() } 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; return c } n.extend({\r\n 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) {\r\n M.remove(a, b)\r\n }, _data: function (a, b, c) { return L.access(a, b, c) }, _removeData: function (a, b) { L.remove(a, b) }\r\n }), 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 = \"\", 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--) if (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.namespace = 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.removeEventListener && 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*\\s*$/g, ib = { option: [1, \"\"], thead: [1, \"\", \"
\"], col: [2, \"\", \"
\"], tr: [2, \"\", \"
\"], td: [3, \"\", \"
\"], _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)) } } function 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>\") + 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.nodeType || 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>\"); 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(\"\"),\n NS = \".kendoTooltip\",\n POSITIONS = {\n bottom: {\n origin: \"bottom center\",\n position: \"top center\"\n },\n top: {\n origin: \"top center\",\n position: \"bottom center\"\n },\n left: {\n origin: \"center left\",\n position: \"center right\",\n collision: \"fit flip\"\n },\n right: {\n origin: \"center right\",\n position: \"center left\",\n collision: \"fit flip\"\n },\n center: {\n position: \"center center\",\n origin: \"center center\"\n }\n },\n REVERSE = {\n \"top\": \"bottom\",\n \"bottom\": \"top\",\n \"left\": \"right\",\n \"right\": \"left\",\n \"center\": \"center\"\n },\n DIRCLASSES = {\n bottom: \"n\",\n top: \"s\",\n left: \"e\",\n right: \"w\",\n center: \"n\"\n },\n DIMENSIONS = {\n \"horizontal\": { offset: \"top\", size: \"outerHeight\" },\n \"vertical\": { offset: \"left\", size: \"outerWidth\" }\n },\n DEFAULTCONTENT = function(e) {\n return e.target.data(kendo.ns + \"title\");\n };\n\n function restoreTitle(element) {\n while(element.length) {\n restoreTitleAttributeForElement(element);\n element = element.parent();\n }\n }\n\n function restoreTitleAttributeForElement(element) {\n var title = element.data(kendo.ns + \"title\");\n if (title) {\n element.attr(\"title\", title);\n element.removeData(kendo.ns + \"title\");\n }\n }\n\n function saveTitleAttributeForElement(element) {\n var title = element.attr(\"title\");\n if (title) {\n element.data(kendo.ns + \"title\", title);\n element.attr(\"title\", \"\");\n }\n }\n\n function saveTitleAttributes(element) {\n while(element.length && !element.is(\"body\")) {\n saveTitleAttributeForElement(element);\n element = element.parent();\n }\n }\n\n var Tooltip = Widget.extend({\n init: function(element, options) {\n var that = this,\n axis;\n\n Widget.fn.init.call(that, element, options);\n\n axis = that.options.position.match(/left|right/) ? \"horizontal\" : \"vertical\";\n\n that.dimensions = DIMENSIONS[axis];\n\n that._documentKeyDownHandler = proxy(that._documentKeyDown, that);\n\n that.element\n .on(that.options.showOn + NS, that.options.filter, proxy(that._showOn, that))\n .on(\"mouseenter\" + NS, that.options.filter, proxy(that._mouseenter, that));\n\n if (this.options.autoHide) {\n that.element.on(\"mouseleave\" + NS, that.options.filter, proxy(that._mouseleave, that));\n }\n },\n\n options: {\n name: \"Tooltip\",\n filter: \"\",\n content: DEFAULTCONTENT,\n showAfter: 100,\n callout: true,\n position: \"bottom\",\n showOn: \"mouseenter\",\n autoHide: true,\n width: null,\n height: null,\n animation: {\n open: {\n effects: \"fade:in\",\n duration: 0\n },\n close: {\n effects: \"fade:out\",\n duration: 40,\n hide: true\n }\n }\n },\n\n events: [ SHOW, HIDE, CONTENTLOAD, ERROR, REQUESTSTART ],\n\n _mouseenter: function(e) {\n saveTitleAttributes($(e.currentTarget));\n },\n\n _showOn: function(e) {\n var that = this;\n\n var currentTarget = $(e.currentTarget);\n if (that.options.showOn && that.options.showOn.match(/click|focus/)) {\n that._show(currentTarget);\n } else {\n clearTimeout(that.timeout);\n\n that.timeout = setTimeout(function() {\n that._show(currentTarget);\n }, that.options.showAfter);\n }\n },\n\n _appendContent: function(target) {\n var that = this,\n contentOptions = that.options.content,\n element = that.content,\n showIframe = that.options.iframe,\n iframe;\n\n if (isPlainObject(contentOptions) && contentOptions.url) {\n if (!(\"iframe\" in that.options)) {\n showIframe = !isLocalUrl(contentOptions.url);\n }\n\n that.trigger(REQUESTSTART, { options: contentOptions, target: target });\n\n if (!showIframe) {\n element.empty();\n kendo.ui.progress(element, true);\n\n // perform AJAX request\n that._ajaxRequest(contentOptions);\n } else {\n element.hide();\n\n iframe = element.find(\".\" + KCONTENTFRAME)[0];\n\n if (iframe) {\n // refresh existing iframe\n iframe.src = contentOptions.url || iframe.src;\n } else {\n element.html(IFRAMETEMPLATE({ content: contentOptions }));\n }\n\n element.find(\".\" + KCONTENTFRAME)\n .off(\"load\" + NS)\n .on(\"load\" + NS, function(){\n that.trigger(CONTENTLOAD);\n element.show();\n });\n }\n } else if (contentOptions && isFunction(contentOptions)) {\n contentOptions = contentOptions({ sender: this, target: target });\n element.html(contentOptions || \"\");\n } else {\n element.html(contentOptions);\n }\n\n that.angular(\"compile\", function(){\n return { elements: element };\n });\n },\n\n _ajaxRequest: function(options) {\n var that = this;\n\n jQuery.ajax(extend({\n type: \"GET\",\n dataType: \"html\",\n cache: false,\n error: function (xhr, status) {\n kendo.ui.progress(that.content, false);\n\n that.trigger(ERROR, { status: status, xhr: xhr });\n },\n success: proxy(function (data) {\n kendo.ui.progress(that.content, false);\n\n that.content.html(data);\n\n that.trigger(CONTENTLOAD);\n }, that)\n }, options));\n },\n\n _documentKeyDown: function(e) {\n if (e.keyCode === kendo.keys.ESC) {\n this.hide();\n }\n },\n\n refresh: function() {\n var that = this,\n popup = that.popup;\n\n if (popup && popup.options.anchor) {\n that._appendContent(popup.options.anchor);\n }\n },\n\n hide: function() {\n if (this.popup) {\n this.popup.close();\n }\n },\n\n show: function(target) {\n target = target || this.element;\n\n saveTitleAttributes(target);\n this._show(target);\n },\n\n _show: function(target) {\n var that = this,\n current = that.target();\n\n if (!that.popup) {\n that._initPopup();\n }\n\n if (current && current[0] != target[0]) {\n that.popup.close();\n that.popup.element.kendoStop(true, true);// animation can be too long to hide the element before it is shown again\n }\n\n if (!current || current[0] != target[0]) {\n that._appendContent(target);\n that.popup.options.anchor = target;\n }\n\n that.popup.one(\"deactivate\", function() {\n restoreTitle(target);\n target.removeAttr(DESCRIBEDBY);\n\n this.element\n .removeAttr(\"id\")\n .attr(\"aria-hidden\", true);\n\n DOCUMENT.off(\"keydown\" + NS, that._documentKeyDownHandler);\n });\n\n that.popup.open();\n },\n\n _initPopup: function() {\n var that = this,\n options = that.options,\n wrapper = $(kendo.template(TEMPLATE)({\n callout: options.callout && options.position !== \"center\",\n dir: DIRCLASSES[options.position],\n autoHide: options.autoHide\n }));\n\n that.popup = new Popup(wrapper, extend({\n activate: function() {\n var anchor = this.options.anchor,\n ariaId = anchor[0].id || that.element[0].id;\n\n if (ariaId) {\n anchor.attr(DESCRIBEDBY, ariaId + ARIAIDSUFFIX);\n this.element.attr(\"id\", ariaId + ARIAIDSUFFIX);\n }\n\n if (options.callout) {\n that._positionCallout();\n }\n\n this.element.removeAttr(\"aria-hidden\");\n\n DOCUMENT.on(\"keydown\" + NS, that._documentKeyDownHandler);\n\n that.trigger(SHOW);\n },\n close: function() {\n that.trigger(HIDE);\n },\n copyAnchorStyles: false,\n animation: options.animation\n }, POSITIONS[options.position]));\n\n wrapper.css({\n width: options.width,\n height: options.height\n });\n\n that.content = wrapper.find(\".k-tooltip-content\");\n that.arrow = wrapper.find(\".k-callout\");\n\n if (options.autoHide) {\n wrapper.on(\"mouseleave\" + NS, proxy(that._mouseleave, that));\n } else {\n wrapper.on(\"click\" + NS, \".k-tooltip-button\", proxy(that._closeButtonClick, that));\n }\n },\n\n _closeButtonClick: function(e) {\n e.preventDefault();\n this.hide();\n },\n\n _mouseleave: function(e) {\n if (this.popup) {\n var element = $(e.currentTarget),\n offset = element.offset(),\n pageX = e.pageX,\n pageY = e.pageY;\n\n offset.right = offset.left + element.outerWidth();\n offset.bottom = offset.top + element.outerHeight();\n\n if (pageX > offset.left && pageX < offset.right && pageY > offset.top && pageY < offset.bottom) {\n return;\n }\n\n this.popup.close();\n } else {\n restoreTitle($(e.currentTarget));\n }\n clearTimeout(this.timeout);\n },\n\n _positionCallout: function() {\n var that = this,\n position = that.options.position,\n dimensions = that.dimensions,\n offset = dimensions.offset,\n popup = that.popup,\n anchor = popup.options.anchor,\n anchorOffset = $(anchor).offset(),\n arrowBorder = parseInt(that.arrow.css(\"border-top-width\"), 10),\n elementOffset = $(popup.element).offset(),\n cssClass = DIRCLASSES[popup.flipped ? REVERSE[position] : position],\n offsetAmount = anchorOffset[offset] - elementOffset[offset] + ($(anchor)[dimensions.size]() / 2) - arrowBorder;\n\n that.arrow\n .removeClass(\"k-callout-n k-callout-s k-callout-w k-callout-e\")\n .addClass(\"k-callout-\" + cssClass)\n .css(offset, offsetAmount);\n },\n\n target: function() {\n if (this.popup) {\n return this.popup.options.anchor;\n }\n return null;\n },\n\n destroy: function() {\n var popup = this.popup;\n\n if (popup) {\n popup.element.off(NS);\n popup.destroy();\n }\n\n this.element.off(NS);\n\n DOCUMENT.off(\"keydown\" + NS, this._documentKeyDownHandler);\n\n Widget.fn.destroy.call(this);\n }\n });\n\n kendo.ui.plugin(Tooltip);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.draganddrop\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n Widget = kendo.ui.Widget,\n Draggable = kendo.ui.Draggable,\n isPlainObject = $.isPlainObject,\n activeElement = kendo._activeElement,\n proxy = $.proxy,\n extend = $.extend,\n each = $.each,\n template = kendo.template,\n BODY = \"body\",\n templates,\n NS = \".kendoWindow\",\n // classNames\n KWINDOW = \".k-window\",\n KWINDOWTITLE = \".k-window-title\",\n KWINDOWTITLEBAR = KWINDOWTITLE + \"bar\",\n KWINDOWCONTENT = \".k-window-content\",\n KWINDOWRESIZEHANDLES = \".k-resize-handle\",\n KOVERLAY = \".k-overlay\",\n KCONTENTFRAME = \"k-content-frame\",\n LOADING = \"k-loading\",\n KHOVERSTATE = \"k-state-hover\",\n KFOCUSEDSTATE = \"k-state-focused\",\n MAXIMIZEDSTATE = \"k-window-maximized\",\n // constants\n VISIBLE = \":visible\",\n HIDDEN = \"hidden\",\n CURSOR = \"cursor\",\n // events\n OPEN = \"open\",\n ACTIVATE = \"activate\",\n DEACTIVATE = \"deactivate\",\n CLOSE = \"close\",\n REFRESH = \"refresh\",\n RESIZE = \"resize\",\n DRAGSTART = \"dragstart\",\n DRAGEND = \"dragend\",\n ERROR = \"error\",\n OVERFLOW = \"overflow\",\n ZINDEX = \"zIndex\",\n MINIMIZE_MAXIMIZE = \".k-window-actions .k-i-minimize,.k-window-actions .k-i-maximize\",\n KPIN = \".k-i-pin\",\n KUNPIN = \".k-i-unpin\",\n PIN_UNPIN = KPIN + \",\" + KUNPIN,\n TITLEBAR_BUTTONS = \".k-window-titlebar .k-window-action\",\n REFRESHICON = \".k-window-titlebar .k-i-refresh\",\n isLocalUrl = kendo.isLocalUrl;\n\n function defined(x) {\n return (typeof x != \"undefined\");\n }\n\n function constrain(value, low, high) {\n return Math.max(Math.min(parseInt(value, 10), high === Infinity ? high : parseInt(high, 10)), parseInt(low, 10));\n }\n\n function sizingAction(actionId, callback) {\n return function() {\n var that = this,\n wrapper = that.wrapper,\n style = wrapper[0].style,\n options = that.options;\n\n if (options.isMaximized || options.isMinimized) {\n return;\n }\n\n that.restoreOptions = {\n width: style.width,\n height: style.height\n };\n\n wrapper\n .children(KWINDOWRESIZEHANDLES).hide().end()\n .children(KWINDOWTITLEBAR).find(MINIMIZE_MAXIMIZE).parent().hide()\n .eq(0).before(templates.action({ name: \"Restore\" }));\n\n callback.call(that);\n\n if (actionId == \"maximize\") {\n that.wrapper.children(KWINDOWTITLEBAR).find(PIN_UNPIN).parent().hide();\n } else {\n that.wrapper.children(KWINDOWTITLEBAR).find(PIN_UNPIN).parent().show();\n }\n\n return that;\n };\n }\n\n function executableScript() {\n return !this.type || this.type.toLowerCase().indexOf(\"script\") >= 0;\n }\n\n var Window = Widget.extend({\n init: function(element, options) {\n var that = this,\n wrapper,\n offset = {},\n visibility, display, position,\n isVisible = false,\n content,\n windowContent,\n suppressActions = options && options.actions && !options.actions.length,\n id;\n\n Widget.fn.init.call(that, element, options);\n options = that.options;\n position = options.position;\n element = that.element;\n content = options.content;\n\n if (suppressActions) {\n options.actions = [];\n }\n\n that.appendTo = $(options.appendTo);\n\n that._animations();\n\n if (content && !isPlainObject(content)) {\n content = options.content = { url: content };\n }\n\n // remove script blocks to prevent double-execution\n element.find(\"script\").filter(executableScript).remove();\n\n if (!element.parent().is(that.appendTo) && (position.top === undefined || position.left === undefined)) {\n if (element.is(VISIBLE)) {\n offset = element.offset();\n isVisible = true;\n } else {\n visibility = element.css(\"visibility\");\n display = element.css(\"display\");\n\n element.css({ visibility: HIDDEN, display: \"\" });\n offset = element.offset();\n element.css({ visibility: visibility, display: display });\n }\n\n if (position.top === undefined) {\n position.top = offset.top;\n }\n if (position.left === undefined) {\n position.left = offset.left;\n }\n }\n\n if (!defined(options.visible) || options.visible === null) {\n options.visible = element.is(VISIBLE);\n }\n\n wrapper = that.wrapper = element.closest(KWINDOW);\n\n if (!element.is(\".k-content\") || !wrapper[0]) {\n element.addClass(\"k-window-content k-content\");\n that._createWindow(element, options);\n wrapper = that.wrapper = element.closest(KWINDOW);\n\n that._dimensions();\n }\n\n that._position();\n\n if (options.pinned) {\n that.pin(true);\n }\n\n if (content) {\n that.refresh(content);\n }\n\n if (options.visible) {\n that.toFront();\n }\n\n windowContent = wrapper.children(KWINDOWCONTENT);\n that._tabindex(windowContent);\n\n if (options.visible && options.modal) {\n that._overlay(wrapper.is(VISIBLE)).css({ opacity: 0.5 });\n }\n\n wrapper\n .on(\"mouseenter\" + NS, TITLEBAR_BUTTONS, proxy(that._buttonEnter, that))\n .on(\"mouseleave\" + NS, TITLEBAR_BUTTONS, proxy(that._buttonLeave, that))\n .on(\"click\" + NS, \"> \" + TITLEBAR_BUTTONS, proxy(that._windowActionHandler, that));\n\n windowContent\n .on(\"keydown\" + NS, proxy(that._keydown, that))\n .on(\"focus\" + NS, proxy(that._focus, that))\n .on(\"blur\" + NS, proxy(that._blur, that));\n\n this._resizable();\n\n this._draggable();\n\n id = element.attr(\"id\");\n if (id) {\n id = id + \"_wnd_title\";\n wrapper.children(KWINDOWTITLEBAR)\n .children(KWINDOWTITLE)\n .attr(\"id\", id);\n\n windowContent\n .attr({\n \"role\": \"dialog\",\n \"aria-labelledby\": id\n });\n }\n\n wrapper.add(wrapper.children(\".k-resize-handle,\" + KWINDOWTITLEBAR))\n .on(\"mousedown\" + NS, proxy(that.toFront, that));\n\n that.touchScroller = kendo.touchScroller(element);\n\n that._resizeHandler = proxy(that._onDocumentResize, that);\n\n $(window).on(\"resize\", that._resizeHandler);\n\n if (options.visible) {\n that.trigger(OPEN);\n that.trigger(ACTIVATE);\n }\n\n kendo.notify(that);\n },\n\n _buttonEnter: function(e) {\n $(e.currentTarget).addClass(KHOVERSTATE);\n },\n\n _buttonLeave: function(e) {\n $(e.currentTarget).removeClass(KHOVERSTATE);\n },\n\n _focus: function() {\n this.wrapper.addClass(KFOCUSEDSTATE);\n },\n\n _blur: function() {\n this.wrapper.removeClass(KFOCUSEDSTATE);\n },\n\n _dimensions: function() {\n var wrapper = this.wrapper;\n var options = this.options;\n var width = options.width;\n var height = options.height;\n var maxHeight = options.maxHeight;\n var dimensions = [\"minWidth\",\"minHeight\",\"maxWidth\",\"maxHeight\"];\n\n this.title(options.title);\n\n for (var i = 0; i < dimensions.length; i++) {\n var value = options[dimensions[i]];\n if (value && value != Infinity) {\n wrapper.css(dimensions[i], value);\n }\n }\n\n if (maxHeight && maxHeight != Infinity) {\n this.element.css(\"maxHeight\", maxHeight);\n }\n\n if (width) {\n if (width.toString().indexOf(\"%\") > 0) {\n wrapper.width(width);\n } else {\n wrapper.width(constrain(width, options.minWidth, options.maxWidth));\n }\n }\n\n if (height) {\n if (height.toString().indexOf(\"%\") > 0) {\n wrapper.height(height);\n } else {\n wrapper.height(constrain(height, options.minHeight, options.maxHeight));\n }\n }\n\n if (!options.visible) {\n wrapper.hide();\n }\n },\n\n _position: function() {\n var wrapper = this.wrapper,\n position = this.options.position;\n\n if (position.top === 0) {\n position.top = position.top.toString();\n }\n\n if (position.left === 0) {\n position.left = position.left.toString();\n }\n\n wrapper.css({\n top: position.top || \"\",\n left: position.left || \"\"\n });\n },\n\n _animations: function() {\n var options = this.options;\n\n if (options.animation === false) {\n options.animation = { open: { effects: {} }, close: { hide: true, effects: {} } };\n }\n },\n\n _resize: function() {\n kendo.resize(this.element.children());\n },\n\n _resizable: function() {\n var resizable = this.options.resizable;\n var wrapper = this.wrapper;\n\n if (this.resizing) {\n wrapper\n .off(\"dblclick\" + NS)\n .children(KWINDOWRESIZEHANDLES).remove();\n\n this.resizing.destroy();\n this.resizing = null;\n }\n\n if (resizable) {\n wrapper.on(\"dblclick\" + NS, KWINDOWTITLEBAR, proxy(function(e) {\n if (!$(e.target).closest(\".k-window-action\").length) {\n this.toggleMaximization();\n }\n }, this));\n\n each(\"n e s w se sw ne nw\".split(\" \"), function(index, handler) {\n wrapper.append(templates.resizeHandle(handler));\n });\n\n this.resizing = new WindowResizing(this);\n }\n\n wrapper = null;\n },\n\n _draggable: function() {\n var draggable = this.options.draggable;\n\n if (this.dragging) {\n this.dragging.destroy();\n this.dragging = null;\n }\n if (draggable) {\n this.dragging = new WindowDragging(this, draggable.dragHandle || KWINDOWTITLEBAR);\n }\n },\n\n setOptions: function(options) {\n Widget.fn.setOptions.call(this, options);\n this._animations();\n this._dimensions();\n this._position();\n this._resizable();\n this._draggable();\n },\n\n events:[\n OPEN,\n ACTIVATE,\n DEACTIVATE,\n CLOSE,\n REFRESH,\n RESIZE,\n DRAGSTART,\n DRAGEND,\n ERROR\n ],\n\n options: {\n name: \"Window\",\n animation: {\n open: {\n effects: { zoom: { direction: \"in\" }, fade: { direction: \"in\" } },\n duration: 350\n },\n close: {\n effects: { zoom: { direction: \"out\", properties: { scale: 0.7 } }, fade: { direction: \"out\" } },\n duration: 350,\n hide: true\n }\n },\n title: \"\",\n actions: [\"Close\"],\n autoFocus: true,\n modal: false,\n resizable: true,\n draggable: true,\n minWidth: 90,\n minHeight: 50,\n maxWidth: Infinity,\n maxHeight: Infinity,\n pinned: false,\n position: {},\n content: null,\n visible: null,\n height: null,\n width: null,\n appendTo: \"body\"\n },\n\n _closable: function() {\n return $.inArray(\"close\", $.map(this.options.actions, function(x) { return x.toLowerCase(); })) > -1;\n },\n\n _keydown: function(e) {\n var that = this,\n options = that.options,\n keys = kendo.keys,\n keyCode = e.keyCode,\n wrapper = that.wrapper,\n offset, handled,\n distance = 10,\n isMaximized = that.options.isMaximized,\n newWidth, newHeight, w, h;\n\n if (e.target != e.currentTarget || that._closing) {\n return;\n }\n\n if (keyCode == keys.ESC && that._closable()) {\n that._close(false);\n }\n\n if (options.draggable && !e.ctrlKey && !isMaximized) {\n offset = kendo.getOffset(wrapper);\n\n if (keyCode == keys.UP) {\n handled = wrapper.css(\"top\", offset.top - distance);\n } else if (keyCode == keys.DOWN) {\n handled = wrapper.css(\"top\", offset.top + distance);\n } else if (keyCode == keys.LEFT) {\n handled = wrapper.css(\"left\", offset.left - distance);\n } else if (keyCode == keys.RIGHT) {\n handled = wrapper.css(\"left\", offset.left + distance);\n }\n }\n\n if (options.resizable && e.ctrlKey && !isMaximized) {\n if (keyCode == keys.UP) {\n handled = true;\n newHeight = wrapper.height() - distance;\n } else if (keyCode == keys.DOWN) {\n handled = true;\n newHeight = wrapper.height() + distance;\n } if (keyCode == keys.LEFT) {\n handled = true;\n newWidth = wrapper.width() - distance;\n } else if (keyCode == keys.RIGHT) {\n handled = true;\n newWidth = wrapper.width() + distance;\n }\n\n if (handled) {\n w = constrain(newWidth, options.minWidth, options.maxWidth);\n h = constrain(newHeight, options.minHeight, options.maxHeight);\n\n if (!isNaN(w)) {\n wrapper.width(w);\n that.options.width = w + \"px\";\n }\n if (!isNaN(h)) {\n wrapper.height(h);\n that.options.height = h + \"px\";\n }\n\n that.resize();\n }\n }\n\n if (handled) {\n e.preventDefault();\n }\n },\n\n _overlay: function (visible) {\n var overlay = this.appendTo.children(KOVERLAY),\n wrapper = this.wrapper;\n\n if (!overlay.length) {\n overlay = $(\"
\");\n }\n\n overlay\n .insertBefore(wrapper[0])\n .toggle(visible)\n .css(ZINDEX, parseInt(wrapper.css(ZINDEX), 10) - 1);\n\n return overlay;\n },\n\n _actionForIcon: function(icon) {\n var iconClass = /\\bk-i-\\w+\\b/.exec(icon[0].className)[0];\n\n return {\n \"k-i-close\": \"_close\",\n \"k-i-maximize\": \"maximize\",\n \"k-i-minimize\": \"minimize\",\n \"k-i-restore\": \"restore\",\n \"k-i-refresh\": \"refresh\",\n \"k-i-pin\": \"pin\",\n \"k-i-unpin\": \"unpin\"\n }[iconClass];\n },\n\n _windowActionHandler: function (e) {\n if (this._closing) {\n return;\n }\n\n var icon = $(e.target).closest(\".k-window-action\").find(\".k-icon\");\n var action = this._actionForIcon(icon);\n\n if (action) {\n e.preventDefault();\n this[action]();\n return false;\n }\n },\n\n _modals: function() {\n var that = this;\n\n var zStack = $(KWINDOW).filter(function() {\n var dom = $(this);\n var object = that._object(dom);\n var options = object && object.options;\n\n return options && options.modal && options.visible && dom.is(VISIBLE);\n }).sort(function(a, b){\n return +$(a).css(\"zIndex\") - +$(b).css(\"zIndex\");\n });\n\n that = null;\n\n return zStack;\n },\n\n _object: function(element) {\n var content = element.children(KWINDOWCONTENT);\n\n return content.data(\"kendoWindow\") || content.data(\"kendo\" + this.options.name);\n },\n\n center: function () {\n var that = this,\n position = that.options.position,\n wrapper = that.wrapper,\n documentWindow = $(window),\n scrollTop = 0,\n scrollLeft = 0,\n newTop, newLeft;\n\n if (that.options.isMaximized) {\n return that;\n }\n\n if (!that.options.pinned) {\n scrollTop = documentWindow.scrollTop();\n scrollLeft = documentWindow.scrollLeft();\n }\n\n newLeft = scrollLeft + Math.max(0, (documentWindow.width() - wrapper.width()) / 2);\n newTop = scrollTop + Math.max(0, (documentWindow.height() - wrapper.height() - parseInt(wrapper.css(\"paddingTop\"), 10)) / 2);\n\n wrapper.css({\n left: newLeft,\n top: newTop\n });\n\n position.top = newTop;\n position.left = newLeft;\n\n return that;\n },\n\n title: function (text) {\n var that = this,\n wrapper = that.wrapper,\n options = that.options,\n titleBar = wrapper.children(KWINDOWTITLEBAR),\n title = titleBar.children(KWINDOWTITLE),\n titleBarHeight = titleBar.outerHeight();\n\n if (!arguments.length) {\n return title.text();\n }\n\n if (text === false) {\n wrapper.addClass(\"k-window-titleless\");\n titleBar.remove();\n } else {\n if (!titleBar.length) {\n wrapper.prepend(templates.titlebar(extend(templates, options)));\n }\n\n wrapper.css(\"padding-top\", titleBarHeight);\n titleBar.css(\"margin-top\", -titleBarHeight);\n }\n\n title.text(text);\n that.options.title = text;\n\n return that;\n },\n\n content: function (html, data) {\n var content = this.wrapper.children(KWINDOWCONTENT),\n scrollContainer = content.children(\".km-scroll-container\");\n\n content = scrollContainer[0] ? scrollContainer : content;\n\n if (!defined(html)) {\n return content.html();\n }\n\n this.angular(\"cleanup\", function(){\n return { elements: content.children() };\n });\n\n kendo.destroy(this.element.children());\n\n content.empty().html(html);\n\n this.angular(\"compile\", function(){\n var a = [];\n for (var i = content.length; --i >= 0;) {\n a.push({ dataItem: data });\n }\n return {\n elements: content.children(),\n data: a\n };\n });\n\n return this;\n },\n\n open: function () {\n var that = this,\n wrapper = that.wrapper,\n options = that.options,\n showOptions = options.animation.open,\n contentElement = wrapper.children(KWINDOWCONTENT),\n overlay;\n\n if (!that.trigger(OPEN)) {\n if (that._closing) {\n wrapper.kendoStop(true, true);\n }\n\n that._closing = false;\n\n that.toFront();\n\n if (options.autoFocus) {\n that.element.focus();\n }\n\n options.visible = true;\n\n if (options.modal) {\n overlay = that._overlay(false);\n\n overlay.kendoStop(true, true);\n\n if (showOptions.duration && kendo.effects.Fade) {\n var overlayFx = kendo.fx(overlay).fadeIn();\n overlayFx.duration(showOptions.duration || 0);\n overlayFx.endValue(0.5);\n overlayFx.play();\n } else {\n overlay.css(\"opacity\", 0.5);\n }\n\n overlay.show();\n }\n\n if (!wrapper.is(VISIBLE)) {\n contentElement.css(OVERFLOW, HIDDEN);\n wrapper.show().kendoStop().kendoAnimate({\n effects: showOptions.effects,\n duration: showOptions.duration,\n complete: proxy(this._activate, this)\n });\n }\n }\n\n if (options.isMaximized) {\n that._documentScrollTop = $(document).scrollTop();\n $(\"html, body\").css(OVERFLOW, HIDDEN);\n }\n\n return that;\n },\n\n _activate: function() {\n if (this.options.autoFocus) {\n this.element.focus();\n }\n this.trigger(ACTIVATE);\n this.wrapper.children(KWINDOWCONTENT).css(OVERFLOW, \"\");\n },\n\n _removeOverlay: function(suppressAnimation) {\n var modals = this._modals();\n var options = this.options;\n var hideOverlay = options.modal && !modals.length;\n var overlay = options.modal ? this._overlay(true) : $(undefined);\n var hideOptions = options.animation.close;\n\n if (hideOverlay) {\n if (!suppressAnimation && hideOptions.duration && kendo.effects.Fade) {\n var overlayFx = kendo.fx(overlay).fadeOut();\n overlayFx.duration(hideOptions.duration || 0);\n overlayFx.startValue(0.5);\n overlayFx.play();\n } else {\n this._overlay(false).remove();\n }\n } else if (modals.length) {\n this._object(modals.last())._overlay(true);\n }\n },\n\n _close: function(systemTriggered) {\n var that = this,\n wrapper = that.wrapper,\n options = that.options,\n showOptions = options.animation.open,\n hideOptions = options.animation.close;\n\n if (wrapper.is(VISIBLE) && !that.trigger(CLOSE, { userTriggered: !systemTriggered })) {\n that._closing = true;\n options.visible = false;\n\n $(KWINDOW).each(function(i, element) {\n var contentElement = $(element).children(KWINDOWCONTENT);\n\n // Remove overlay set by toFront\n if (element != wrapper && contentElement.find(\"> .\" + KCONTENTFRAME).length > 0) {\n contentElement.children(KOVERLAY).remove();\n }\n });\n\n this._removeOverlay();\n\n wrapper.kendoStop().kendoAnimate({\n effects: hideOptions.effects || showOptions.effects,\n reverse: hideOptions.reverse === true,\n duration: hideOptions.duration,\n complete: proxy(this._deactivate, this)\n });\n }\n\n if (that.options.isMaximized) {\n $(\"html, body\").css(OVERFLOW, \"\");\n if (that._documentScrollTop && that._documentScrollTop > 0) {\n $(document).scrollTop(that._documentScrollTop);\n }\n }\n },\n\n _deactivate: function() {\n this.wrapper.hide().css(\"opacity\",\"\");\n this.trigger(DEACTIVATE);\n var lastModal = this._object(this._modals().last());\n if (lastModal) {\n lastModal.toFront();\n }\n },\n\n close: function () {\n this._close(true);\n return this;\n },\n\n _actionable: function(element) {\n return $(element).is(TITLEBAR_BUTTONS + \",\" + TITLEBAR_BUTTONS + \" .k-icon,:input,a\");\n },\n\n _shouldFocus: function(target) {\n var active = activeElement(),\n element = this.element;\n\n return this.options.autoFocus &&\n !$(active).is(element) &&\n !this._actionable(target) &&\n (!element.find(active).length || !element.find(target).length);\n },\n\n toFront: function (e) {\n var that = this,\n wrapper = that.wrapper,\n currentWindow = wrapper[0],\n zIndex = +wrapper.css(ZINDEX),\n originalZIndex = zIndex,\n target = (e && e.target) || null;\n\n $(KWINDOW).each(function(i, element) {\n var windowObject = $(element),\n zIndexNew = windowObject.css(ZINDEX),\n contentElement = windowObject.children(KWINDOWCONTENT);\n\n if (!isNaN(zIndexNew)) {\n zIndex = Math.max(+zIndexNew, zIndex);\n }\n\n // Add overlay to windows with iframes and lower z-index to prevent\n // trapping of events when resizing / dragging\n if (element != currentWindow && contentElement.find(\"> .\" + KCONTENTFRAME).length > 0) {\n contentElement.append(templates.overlay);\n }\n });\n\n if (!wrapper[0].style.zIndex || originalZIndex < zIndex) {\n wrapper.css(ZINDEX, zIndex + 2);\n }\n that.element.find(\"> .k-overlay\").remove();\n\n if (that._shouldFocus(target)) {\n that.element.focus();\n\n var scrollTop = $(window).scrollTop(),\n windowTop = parseInt(wrapper.position().top, 10);\n\n if (windowTop > 0 && windowTop < scrollTop) {\n if (scrollTop > 0) {\n $(window).scrollTop(windowTop);\n } else {\n wrapper.css(\"top\", scrollTop);\n }\n }\n }\n\n wrapper = null;\n\n return that;\n },\n\n toggleMaximization: function () {\n if (this._closing) {\n return this;\n }\n\n return this[this.options.isMaximized ? \"restore\" : \"maximize\"]();\n },\n\n restore: function () {\n var that = this;\n var options = that.options;\n var minHeight = options.minHeight;\n var restoreOptions = that.restoreOptions;\n\n if (!options.isMaximized && !options.isMinimized) {\n return that;\n }\n\n if (minHeight && minHeight != Infinity) {\n that.wrapper.css(\"min-height\", minHeight);\n }\n\n that.wrapper\n .css({\n position: options.pinned ? \"fixed\" : \"absolute\",\n left: restoreOptions.left,\n top: restoreOptions.top,\n width: restoreOptions.width,\n height: restoreOptions.height\n })\n .removeClass(MAXIMIZEDSTATE)\n .find(\".k-window-content,.k-resize-handle\").show().end()\n .find(\".k-window-titlebar .k-i-restore\").parent().remove().end().end()\n .find(MINIMIZE_MAXIMIZE).parent().show().end().end()\n .find(PIN_UNPIN).parent().show();\n\n that.options.width = restoreOptions.width;\n that.options.height = restoreOptions.height;\n\n $(\"html, body\").css(OVERFLOW, \"\");\n if (this._documentScrollTop && this._documentScrollTop > 0) {\n $(document).scrollTop(this._documentScrollTop);\n }\n\n options.isMaximized = options.isMinimized = false;\n\n that.resize();\n\n return that;\n },\n\n maximize: sizingAction(\"maximize\", function() {\n var that = this,\n wrapper = that.wrapper,\n position = wrapper.position();\n\n extend(that.restoreOptions, {\n left: position.left,\n top: position.top\n });\n\n wrapper.css({\n left: 0,\n top: 0,\n position: \"fixed\"\n })\n .addClass(MAXIMIZEDSTATE);\n\n this._documentScrollTop = $(document).scrollTop();\n $(\"html, body\").css(OVERFLOW, HIDDEN);\n\n that.options.isMaximized = true;\n\n that._onDocumentResize();\n }),\n\n minimize: sizingAction(\"minimize\", function() {\n var that = this;\n\n that.wrapper.css({\n height: \"\",\n minHeight: \"\"\n });\n\n that.element.hide();\n\n that.options.isMinimized = true;\n }),\n\n pin: function(force) {\n var that = this,\n win = $(window),\n wrapper = that.wrapper,\n top = parseInt(wrapper.css(\"top\"), 10),\n left = parseInt(wrapper.css(\"left\"), 10);\n\n if (force || !that.options.pinned && !that.options.isMaximized) {\n wrapper.css({position: \"fixed\", top: top - win.scrollTop(), left: left - win.scrollLeft()});\n wrapper.children(KWINDOWTITLEBAR).find(KPIN).addClass(\"k-i-unpin\").removeClass(\"k-i-pin\");\n\n that.options.pinned = true;\n }\n },\n\n unpin: function() {\n var that = this,\n win = $(window),\n wrapper = that.wrapper,\n top = parseInt(wrapper.css(\"top\"), 10),\n left = parseInt(wrapper.css(\"left\"), 10);\n\n if (that.options.pinned && !that.options.isMaximized) {\n wrapper.css({position: \"\", top: top + win.scrollTop(), left: left + win.scrollLeft()});\n wrapper.children(KWINDOWTITLEBAR).find(KUNPIN).addClass(\"k-i-pin\").removeClass(\"k-i-unpin\");\n\n that.options.pinned = false;\n }\n },\n\n _onDocumentResize: function () {\n var that = this,\n wrapper = that.wrapper,\n wnd = $(window),\n w, h;\n\n if (!that.options.isMaximized) {\n return;\n }\n\n w = wnd.width();\n h = wnd.height() - parseInt(wrapper.css(\"padding-top\"), 10);\n\n wrapper.css({\n width: w,\n height: h\n });\n that.options.width = w;\n that.options.height = h;\n\n that.resize();\n },\n\n refresh: function (options) {\n var that = this,\n initOptions = that.options,\n element = $(that.element),\n iframe,\n showIframe,\n url;\n\n if (!isPlainObject(options)) {\n options = { url: options };\n }\n\n options = extend({}, initOptions.content, options);\n\n showIframe = defined(initOptions.iframe) ? initOptions.iframe : options.iframe;\n\n url = options.url;\n\n if (url) {\n if (!defined(showIframe)) {\n showIframe = !isLocalUrl(url);\n }\n\n if (!showIframe) {\n // perform AJAX request\n that._ajaxRequest(options);\n } else {\n iframe = element.find(\".\" + KCONTENTFRAME)[0];\n\n if (iframe) {\n // refresh existing iframe\n iframe.src = url || iframe.src;\n } else {\n // render new iframe\n element.html(templates.contentFrame(extend({}, initOptions, { content: options })));\n }\n\n element.find(\".\" + KCONTENTFRAME)\n .unbind(\"load\" + NS)\n .on(\"load\" + NS, proxy(this._triggerRefresh, this));\n }\n } else {\n if (options.template) {\n // refresh template\n that.content(template(options.template)({}));\n }\n\n that.trigger(REFRESH);\n }\n\n element.toggleClass(\"k-window-iframecontent\", !!showIframe);\n\n return that;\n },\n\n _triggerRefresh: function() {\n this.trigger(REFRESH);\n },\n\n _ajaxComplete: function() {\n clearTimeout(this._loadingIconTimeout);\n this.wrapper.find(REFRESHICON).removeClass(LOADING);\n },\n\n _ajaxError: function (xhr, status) {\n this.trigger(ERROR, { status: status, xhr: xhr });\n },\n\n _ajaxSuccess: function (contentTemplate) {\n return function (data) {\n var html = data;\n if (contentTemplate) {\n html = template(contentTemplate)(data || {});\n }\n\n this.content(html, data);\n this.element.prop(\"scrollTop\", 0);\n\n this.trigger(REFRESH);\n };\n },\n\n _showLoading: function() {\n this.wrapper.find(REFRESHICON).addClass(LOADING);\n },\n\n _ajaxRequest: function (options) {\n this._loadingIconTimeout = setTimeout(proxy(this._showLoading, this), 100);\n\n $.ajax(extend({\n type: \"GET\",\n dataType: \"html\",\n cache: false,\n error: proxy(this._ajaxError, this),\n complete: proxy(this._ajaxComplete, this),\n success: proxy(this._ajaxSuccess(options.template), this)\n }, options));\n },\n\n destroy: function () {\n if (this.resizing) {\n this.resizing.destroy();\n }\n\n if (this.dragging) {\n this.dragging.destroy();\n }\n\n this.wrapper.off(NS)\n .children(KWINDOWCONTENT).off(NS).end()\n .find(\".k-resize-handle,.k-window-titlebar\").off(NS);\n\n $(window).off(\"resize\", this._resizeHandler);\n\n clearTimeout(this._loadingIconTimeout);\n\n Widget.fn.destroy.call(this);\n\n this.unbind(undefined);\n\n kendo.destroy(this.wrapper);\n\n this._removeOverlay(true);\n\n this.wrapper.empty().remove();\n\n this.wrapper = this.appendTo = this.element = $();\n },\n\n _createWindow: function() {\n var contentHtml = this.element,\n options = this.options,\n iframeSrcAttributes,\n wrapper,\n isRtl = kendo.support.isRtl(contentHtml);\n\n if (options.scrollable === false) {\n contentHtml.attr(\"style\", \"overflow:hidden;\");\n }\n\n wrapper = $(templates.wrapper(options));\n\n if (options.title !== false) {\n wrapper.append(templates.titlebar(extend(templates, options)));\n }\n\n // Collect the src attributes of all iframes and then set them to empty string.\n // This seems to fix this IE9 \"feature\": http://msdn.microsoft.com/en-us/library/gg622929%28v=VS.85%29.aspx?ppud=4\n iframeSrcAttributes = contentHtml.find(\"iframe:not(.k-content)\").map(function() {\n var src = this.getAttribute(\"src\");\n this.src = \"\";\n return src;\n });\n\n // Make sure the wrapper is appended to the body only once. IE9+ will throw exceptions if you move iframes in DOM\n wrapper\n .toggleClass(\"k-rtl\", isRtl)\n .appendTo(this.appendTo)\n .append(contentHtml)\n .find(\"iframe:not(.k-content)\").each(function(index) {\n // Restore the src attribute of the iframes when they are part of the live DOM tree\n this.src = iframeSrcAttributes[index];\n });\n\n wrapper.find(\".k-window-title\")\n .css(isRtl ? \"left\" : \"right\", wrapper.find(\".k-window-actions\").outerWidth() + 10);\n\n contentHtml.show();\n\n contentHtml.find(\"[data-role=editor]\").each(function() {\n var editor = $(this).data(\"kendoEditor\");\n\n if (editor) {\n editor.refresh();\n }\n });\n\n wrapper = contentHtml = null;\n }\n });\n\n templates = {\n wrapper: template(\"
\"),\n action: template(\n \"\" +\n \"#= name #\" +\n \"\"\n ),\n titlebar: template(\n \"
 \" +\n \"#= title #\" +\n \"
\" +\n \"# for (var i = 0; i < actions.length; i++) { #\" +\n \"#= action({ name: actions[i] }) #\" +\n \"# } #\" +\n \"
\" +\n \"
\"\n ),\n overlay: \"
\",\n contentFrame: template(\n \"\"\n ),\n resizeHandle: template(\"
\")\n };\n\n\n function WindowResizing(wnd) {\n var that = this;\n that.owner = wnd;\n that._draggable = new Draggable(wnd.wrapper, {\n filter: KWINDOWRESIZEHANDLES,\n group: wnd.wrapper.id + \"-resizing\",\n dragstart: proxy(that.dragstart, that),\n drag: proxy(that.drag, that),\n dragend: proxy(that.dragend, that)\n });\n\n that._draggable.userEvents.bind(\"press\", proxy(that.addOverlay, that));\n that._draggable.userEvents.bind(\"release\", proxy(that.removeOverlay, that));\n }\n\n WindowResizing.prototype = {\n addOverlay: function () {\n this.owner.wrapper.append(templates.overlay);\n },\n removeOverlay: function () {\n this.owner.wrapper.find(KOVERLAY).remove();\n },\n dragstart: function (e) {\n var that = this;\n var wnd = that.owner;\n var wrapper = wnd.wrapper;\n\n that.elementPadding = parseInt(wrapper.css(\"padding-top\"), 10);\n that.initialPosition = kendo.getOffset(wrapper, \"position\");\n\n that.resizeDirection = e.currentTarget.prop(\"className\").replace(\"k-resize-handle k-resize-\", \"\");\n\n that.initialSize = {\n width: wrapper.width(),\n height: wrapper.height()\n };\n\n that.containerOffset = kendo.getOffset(wnd.appendTo, \"position\");\n\n wrapper\n .children(KWINDOWRESIZEHANDLES).not(e.currentTarget).hide();\n\n $(BODY).css(CURSOR, e.currentTarget.css(CURSOR));\n },\n drag: function (e) {\n var that = this,\n wnd = that.owner,\n wrapper = wnd.wrapper,\n options = wnd.options,\n direction = that.resizeDirection,\n containerOffset = that.containerOffset,\n initialPosition = that.initialPosition,\n initialSize = that.initialSize,\n newWidth, newHeight,\n windowBottom, windowRight,\n x = Math.max(e.x.location, containerOffset.left),\n y = Math.max(e.y.location, containerOffset.top);\n\n if (direction.indexOf(\"e\") >= 0) {\n newWidth = x - initialPosition.left;\n\n wrapper.width(constrain(newWidth, options.minWidth, options.maxWidth));\n } else if (direction.indexOf(\"w\") >= 0) {\n windowRight = initialPosition.left + initialSize.width;\n newWidth = constrain(windowRight - x, options.minWidth, options.maxWidth);\n\n wrapper.css({\n left: windowRight - newWidth - containerOffset.left,\n width: newWidth\n });\n }\n\n if (direction.indexOf(\"s\") >= 0) {\n newHeight = y - initialPosition.top - that.elementPadding;\n\n wrapper.height(constrain(newHeight, options.minHeight, options.maxHeight));\n } else if (direction.indexOf(\"n\") >= 0) {\n windowBottom = initialPosition.top + initialSize.height;\n newHeight = constrain(windowBottom - y, options.minHeight, options.maxHeight);\n\n wrapper.css({\n top: windowBottom - newHeight - containerOffset.top,\n height: newHeight\n });\n }\n\n if (newWidth) {\n wnd.options.width = newWidth + \"px\";\n }\n if (newHeight) {\n wnd.options.height = newHeight + \"px\";\n }\n\n wnd.resize();\n },\n dragend: function (e) {\n var that = this,\n wnd = that.owner,\n wrapper = wnd.wrapper;\n\n wrapper\n .children(KWINDOWRESIZEHANDLES).not(e.currentTarget).show();\n\n $(BODY).css(CURSOR, \"\");\n\n if (wnd.touchScroller) {\n wnd.touchScroller.reset();\n }\n if (e.keyCode == 27) {\n wrapper.css(that.initialPosition)\n .css(that.initialSize);\n }\n\n return false;\n },\n destroy: function() {\n if (this._draggable) {\n this._draggable.destroy();\n }\n\n this._draggable = this.owner = null;\n }\n };\n\n function WindowDragging(wnd, dragHandle) {\n var that = this;\n that.owner = wnd;\n that._draggable = new Draggable(wnd.wrapper, {\n filter: dragHandle,\n group: wnd.wrapper.id + \"-moving\",\n dragstart: proxy(that.dragstart, that),\n drag: proxy(that.drag, that),\n dragend: proxy(that.dragend, that),\n dragcancel: proxy(that.dragcancel, that)\n });\n\n that._draggable.userEvents.stopPropagation = false;\n }\n\n WindowDragging.prototype = {\n dragstart: function (e) {\n var wnd = this.owner,\n element = wnd.element,\n actions = element.find(\".k-window-actions\"),\n containerOffset = kendo.getOffset(wnd.appendTo);\n\n wnd.trigger(DRAGSTART);\n\n wnd.initialWindowPosition = kendo.getOffset(wnd.wrapper, \"position\");\n\n wnd.startPosition = {\n left: e.x.client - wnd.initialWindowPosition.left,\n top: e.y.client - wnd.initialWindowPosition.top\n };\n\n if (actions.length > 0) {\n wnd.minLeftPosition = actions.outerWidth() + parseInt(actions.css(\"right\"), 10) - element.outerWidth();\n } else {\n wnd.minLeftPosition = 20 - element.outerWidth(); // at least 20px remain visible\n }\n\n wnd.minLeftPosition -= containerOffset.left;\n wnd.minTopPosition = -containerOffset.top;\n\n wnd.wrapper\n .append(templates.overlay)\n .children(KWINDOWRESIZEHANDLES).hide();\n\n $(BODY).css(CURSOR, e.currentTarget.css(CURSOR));\n },\n\n drag: function (e) {\n var wnd = this.owner,\n position = wnd.options.position,\n newTop = Math.max(e.y.client - wnd.startPosition.top, wnd.minTopPosition),\n newLeft = Math.max(e.x.client - wnd.startPosition.left, wnd.minLeftPosition),\n coordinates = {\n left: newLeft,\n top: newTop\n };\n\n $(wnd.wrapper).css(coordinates);\n position.top = newTop;\n position.left = newLeft;\n },\n\n _finishDrag: function() {\n var wnd = this.owner;\n\n wnd.wrapper\n .children(KWINDOWRESIZEHANDLES).toggle(!wnd.options.isMinimized).end()\n .find(KOVERLAY).remove();\n\n $(BODY).css(CURSOR, \"\");\n },\n\n dragcancel: function (e) {\n this._finishDrag();\n\n e.currentTarget.closest(KWINDOW).css(this.owner.initialWindowPosition);\n },\n\n dragend: function () {\n this._finishDrag();\n\n this.owner.trigger(DRAGEND);\n\n return false;\n },\n destroy: function() {\n if (this._draggable) {\n this._draggable.destroy();\n }\n\n this._draggable = this.owner = null;\n }\n };\n\n kendo.ui.plugin(Window);\n\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\", \"./kendo.data\" ], f);\n})(function(){\n\n/*jshint eqnull: true */\n(function ($, undefined) {\n var kendo = window.kendo,\n browser = kendo.support.browser,\n Observable = kendo.Observable,\n ObservableObject = kendo.data.ObservableObject,\n ObservableArray = kendo.data.ObservableArray,\n toString = {}.toString,\n binders = {},\n slice = Array.prototype.slice,\n Class = kendo.Class,\n innerText,\n proxy = $.proxy,\n VALUE = \"value\",\n SOURCE = \"source\",\n EVENTS = \"events\",\n CHECKED = \"checked\",\n deleteExpando = true,\n CHANGE = \"change\";\n\n (function() {\n var a = document.createElement(\"a\");\n\n if (a.innerText !== undefined) {\n innerText = \"innerText\";\n } else if (a.textContent !== undefined) {\n innerText = \"textContent\";\n }\n\n try {\n delete a.test;\n } catch(e) {\n deleteExpando = false;\n }\n })();\n\n var Binding = Observable.extend( {\n init: function(parents, path) {\n var that = this;\n\n Observable.fn.init.call(that);\n\n that.source = parents[0];\n that.parents = parents;\n that.path = path;\n that.dependencies = {};\n that.dependencies[path] = true;\n that.observable = that.source instanceof Observable;\n\n that._access = function(e) {\n that.dependencies[e.field] = true;\n };\n\n if (that.observable) {\n that._change = function(e) {\n that.change(e);\n };\n\n that.source.bind(CHANGE, that._change);\n }\n },\n\n _parents: function() {\n var parents = this.parents;\n var value = this.get();\n\n if (value && typeof value.parent == \"function\") {\n var parent = value.parent();\n\n if ($.inArray(parent, parents) < 0) {\n parents = [parent].concat(parents);\n }\n }\n\n return parents;\n },\n\n change: function(e) {\n var dependency,\n ch,\n field = e.field,\n that = this;\n\n if (that.path === \"this\") {\n that.trigger(CHANGE, e);\n } else {\n for (dependency in that.dependencies) {\n if (dependency.indexOf(field) === 0) {\n ch = dependency.charAt(field.length);\n\n if (!ch || ch === \".\" || ch === \"[\") {\n that.trigger(CHANGE, e);\n break;\n }\n }\n }\n }\n },\n\n start: function(source) {\n source.bind(\"get\", this._access);\n },\n\n stop: function(source) {\n source.unbind(\"get\", this._access);\n },\n\n get: function() {\n\n var that = this,\n source = that.source,\n index = 0,\n path = that.path,\n result = source;\n\n if (!that.observable) {\n return result;\n }\n\n that.start(that.source);\n\n result = source.get(path);\n\n // Traverse the observable hierarchy if the binding is not resolved at the current level.\n while (result === undefined && source) {\n\n source = that.parents[++index];\n\n if (source instanceof ObservableObject) {\n result = source.get(path);\n }\n }\n\n // second pass try to get the parent from the object hierarchy\n if (result === undefined) {\n source = that.source; //get the initial source\n\n while (result === undefined && source) {\n source = source.parent();\n\n if (source instanceof ObservableObject) {\n result = source.get(path);\n }\n }\n }\n\n // If the result is a function - invoke it\n if (typeof result === \"function\") {\n index = path.lastIndexOf(\".\");\n\n // If the function is a member of a nested observable object make that nested observable the context (this) of the function\n if (index > 0) {\n source = source.get(path.substring(0, index));\n }\n\n // Invoke the function\n that.start(source);\n\n if (source !== that.source) {\n result = result.call(source, that.source);\n } else {\n result = result.call(source);\n }\n\n that.stop(source);\n }\n\n // If the binding is resolved by a parent object\n if (source && source !== that.source) {\n\n that.currentSource = source; // save parent object\n\n // Listen for changes in the parent object\n source.unbind(CHANGE, that._change)\n .bind(CHANGE, that._change);\n }\n\n that.stop(that.source);\n\n return result;\n },\n\n set: function(value) {\n var source = this.currentSource || this.source;\n\n var field = kendo.getter(this.path)(source);\n\n if (typeof field === \"function\") {\n if (source !== this.source) {\n field.call(source, this.source, value);\n } else {\n field.call(source, value);\n }\n } else {\n source.set(this.path, value);\n }\n },\n\n destroy: function() {\n if (this.observable) {\n this.source.unbind(CHANGE, this._change);\n }\n\n this.unbind();\n }\n });\n\n var EventBinding = Binding.extend( {\n get: function() {\n var source = this.source,\n path = this.path,\n index = 0,\n handler;\n\n handler = source.get(path);\n\n while (!handler && source) {\n source = this.parents[++index];\n\n if (source instanceof ObservableObject) {\n handler = source.get(path);\n }\n }\n\n return proxy(handler, source);\n }\n });\n\n var TemplateBinding = Binding.extend( {\n init: function(source, path, template) {\n var that = this;\n\n Binding.fn.init.call(that, source, path);\n\n that.template = template;\n },\n\n render: function(value) {\n var html;\n\n this.start(this.source);\n\n html = kendo.render(this.template, value);\n\n this.stop(this.source);\n\n return html;\n }\n });\n\n var Binder = Class.extend({\n init: function(element, bindings, options) {\n this.element = element;\n this.bindings = bindings;\n this.options = options;\n },\n\n bind: function(binding, attribute) {\n var that = this;\n\n binding = attribute ? binding[attribute] : binding;\n\n binding.bind(CHANGE, function(e) {\n that.refresh(attribute || e);\n });\n\n that.refresh(attribute);\n },\n\n destroy: function() {\n }\n });\n\n binders.attr = Binder.extend({\n refresh: function(key) {\n this.element.setAttribute(key, this.bindings.attr[key].get());\n }\n });\n\n binders.style = Binder.extend({\n refresh: function(key) {\n this.element.style[key] = this.bindings.style[key].get() || \"\";\n }\n });\n\n binders.enabled = Binder.extend({\n refresh: function() {\n if (this.bindings.enabled.get()) {\n this.element.removeAttribute(\"disabled\");\n } else {\n this.element.setAttribute(\"disabled\", \"disabled\");\n }\n }\n });\n\n binders.readonly = Binder.extend({\n refresh: function() {\n if (this.bindings.readonly.get()) {\n this.element.setAttribute(\"readonly\", \"readonly\");\n } else {\n this.element.removeAttribute(\"readonly\");\n }\n }\n });\n\n binders.disabled = Binder.extend({\n refresh: function() {\n if (this.bindings.disabled.get()) {\n this.element.setAttribute(\"disabled\", \"disabled\");\n } else {\n this.element.removeAttribute(\"disabled\");\n }\n }\n });\n\n binders.events = Binder.extend({\n init: function(element, bindings, options) {\n Binder.fn.init.call(this, element, bindings, options);\n this.handlers = {};\n },\n\n refresh: function(key) {\n var element = $(this.element),\n binding = this.bindings.events[key],\n handler = this.handlers[key];\n\n if (handler) {\n element.off(key, handler);\n }\n\n handler = this.handlers[key] = binding.get();\n\n element.on(key, binding.source, handler);\n },\n\n destroy: function() {\n var element = $(this.element),\n handler;\n\n for (handler in this.handlers) {\n element.off(handler, this.handlers[handler]);\n }\n }\n });\n\n binders.text = Binder.extend({\n refresh: function() {\n var text = this.bindings.text.get();\n\n if (text == null) {\n text = \"\";\n }\n\n this.element[innerText] = text;\n }\n });\n\n binders.visible = Binder.extend({\n refresh: function() {\n if (this.bindings.visible.get()) {\n this.element.style.display = \"\";\n } else {\n this.element.style.display = \"none\";\n }\n }\n });\n\n binders.invisible = Binder.extend({\n refresh: function() {\n if (!this.bindings.invisible.get()) {\n this.element.style.display = \"\";\n } else {\n this.element.style.display = \"none\";\n }\n }\n });\n\n binders.html = Binder.extend({\n refresh: function() {\n this.element.innerHTML = this.bindings.html.get();\n }\n });\n\n binders.value = Binder.extend({\n init: function(element, bindings, options) {\n Binder.fn.init.call(this, element, bindings, options);\n\n this._change = proxy(this.change, this);\n this.eventName = options.valueUpdate || CHANGE;\n\n $(this.element).on(this.eventName, this._change);\n\n this._initChange = false;\n },\n\n change: function() {\n this._initChange = this.eventName != CHANGE;\n\n var value = this.element.value;\n\n var type = this.element.type;\n\n if (type == \"date\") {\n value = kendo.parseDate(value, \"yyyy-MM-dd\");\n } else if (type == \"datetime-local\") {\n value = kendo.parseDate(value, [\"yyyy-MM-ddTHH:mm:ss\", \"yyyy-MM-ddTHH:mm\"] );\n } else if (type == \"number\") {\n value = kendo.parseFloat(value);\n }\n\n this.bindings[VALUE].set(value);\n\n this._initChange = false;\n },\n\n refresh: function() {\n if (!this._initChange) {\n var value = this.bindings[VALUE].get();\n\n if (value == null) {\n value = \"\";\n }\n\n var type = this.element.type;\n\n if (type == \"date\") {\n value = kendo.toString(value, \"yyyy-MM-dd\");\n } else if (type == \"datetime-local\") {\n value = kendo.toString(value, \"yyyy-MM-ddTHH:mm:ss\");\n }\n\n this.element.value = value;\n }\n\n this._initChange = false;\n },\n\n destroy: function() {\n $(this.element).off(this.eventName, this._change);\n }\n });\n\n binders.source = Binder.extend({\n init: function(element, bindings, options) {\n Binder.fn.init.call(this, element, bindings, options);\n\n var source = this.bindings.source.get();\n\n if (source instanceof kendo.data.DataSource && options.autoBind !== false) {\n source.fetch();\n }\n },\n\n refresh: function(e) {\n var that = this,\n source = that.bindings.source.get();\n\n if (source instanceof ObservableArray || source instanceof kendo.data.DataSource) {\n e = e || {};\n\n if (e.action == \"add\") {\n that.add(e.index, e.items);\n } else if (e.action == \"remove\") {\n that.remove(e.index, e.items);\n } else if (e.action != \"itemchange\") {\n that.render();\n }\n } else {\n that.render();\n }\n },\n\n container: function() {\n var element = this.element;\n\n if (element.nodeName.toLowerCase() == \"table\") {\n if (!element.tBodies[0]) {\n element.appendChild(document.createElement(\"tbody\"));\n }\n element = element.tBodies[0];\n }\n\n return element;\n },\n\n template: function() {\n var options = this.options,\n template = options.template,\n nodeName = this.container().nodeName.toLowerCase();\n\n if (!template) {\n if (nodeName == \"select\") {\n if (options.valueField || options.textField) {\n template = kendo.format('',\n options.valueField || options.textField, options.textField || options.valueField);\n } else {\n template = \"\";\n }\n } else if (nodeName == \"tbody\") {\n template = \"#:data#\";\n } else if (nodeName == \"ul\" || nodeName == \"ol\") {\n template = \"
  • #:data#
  • \";\n } else {\n template = \"#:data#\";\n }\n\n template = kendo.template(template);\n }\n\n return template;\n },\n\n add: function(index, items) {\n var element = this.container(),\n parents,\n idx,\n length,\n child,\n clone = element.cloneNode(false),\n reference = element.children[index];\n\n $(clone).html(kendo.render(this.template(), items));\n\n if (clone.children.length) {\n parents = this.bindings.source._parents();\n\n for (idx = 0, length = items.length; idx < length; idx++) {\n child = clone.children[0];\n element.insertBefore(child, reference || null);\n bindElement(child, items[idx], this.options.roles, [items[idx]].concat(parents));\n }\n }\n },\n\n remove: function(index, items) {\n var idx, element = this.container();\n\n for (idx = 0; idx < items.length; idx++) {\n var child = element.children[index];\n unbindElementTree(child);\n element.removeChild(child);\n }\n },\n\n render: function() {\n var source = this.bindings.source.get(),\n parents,\n idx,\n length,\n element = this.container(),\n template = this.template();\n\n if (source instanceof kendo.data.DataSource) {\n source = source.view();\n }\n\n if (!(source instanceof ObservableArray) && toString.call(source) !== \"[object Array]\") {\n source = [source];\n }\n\n if (this.bindings.template) {\n unbindElementChildren(element);\n\n $(element).html(this.bindings.template.render(source));\n\n if (element.children.length) {\n parents = this.bindings.source._parents();\n\n for (idx = 0, length = source.length; idx < length; idx++) {\n bindElement(element.children[idx], source[idx], this.options.roles, [source[idx]].concat(parents));\n }\n }\n }\n else {\n $(element).html(kendo.render(template, source));\n }\n }\n });\n\n binders.input = {\n checked: Binder.extend({\n init: function(element, bindings, options) {\n Binder.fn.init.call(this, element, bindings, options);\n this._change = proxy(this.change, this);\n\n $(this.element).change(this._change);\n },\n change: function() {\n var element = this.element;\n var value = this.value();\n\n if (element.type == \"radio\") {\n this.bindings[CHECKED].set(value);\n } else if (element.type == \"checkbox\") {\n var source = this.bindings[CHECKED].get();\n var index;\n\n if (source instanceof ObservableArray) {\n value = this.element.value;\n\n if (value !== \"on\" && value !== \"off\") {\n index = source.indexOf(value);\n if (index > -1) {\n source.splice(index, 1);\n } else {\n source.push(value);\n }\n }\n } else {\n this.bindings[CHECKED].set(value);\n }\n }\n },\n\n refresh: function() {\n var value = this.bindings[CHECKED].get(),\n source = value,\n element = this.element;\n\n if (element.type == \"checkbox\") {\n if (source instanceof ObservableArray) {\n value = this.element.value;\n if (source.indexOf(value) >= 0) {\n value = true;\n }\n }\n\n element.checked = value === true;\n } else if (element.type == \"radio\" && value != null) {\n if (element.value === value.toString()) {\n element.checked = true;\n }\n }\n },\n\n value: function() {\n var element = this.element,\n value = element.value;\n\n if (element.type == \"checkbox\") {\n value = element.checked;\n }\n\n return value;\n },\n destroy: function() {\n $(this.element).off(CHANGE, this._change);\n }\n })\n };\n\n binders.select = {\n value: Binder.extend({\n init: function(target, bindings, options) {\n Binder.fn.init.call(this, target, bindings, options);\n\n this._change = proxy(this.change, this);\n $(this.element).change(this._change);\n },\n\n change: function() {\n var values = [],\n element = this.element,\n source,\n field = this.options.valueField || this.options.textField,\n valuePrimitive = this.options.valuePrimitive,\n option,\n valueIndex,\n value,\n idx,\n length;\n\n for (idx = 0, length = element.options.length; idx < length; idx++) {\n option = element.options[idx];\n\n if (option.selected) {\n value = option.attributes.value;\n\n if (value && value.specified) {\n value = option.value;\n } else {\n value = option.text;\n }\n\n values.push(value);\n }\n }\n\n if (field) {\n source = this.bindings.source.get();\n for (valueIndex = 0; valueIndex < values.length; valueIndex++) {\n for (idx = 0, length = source.length; idx < length; idx++) {\n if (source[idx].get(field) == values[valueIndex]) {\n values[valueIndex] = source[idx];\n break;\n }\n }\n }\n }\n\n value = this.bindings[VALUE].get();\n if (value instanceof ObservableArray) {\n value.splice.apply(value, [0, value.length].concat(values));\n } else if (!valuePrimitive && (value instanceof ObservableObject || !field)) {\n this.bindings[VALUE].set(values[0]);\n } else {\n this.bindings[VALUE].set(values[0].get(field));\n }\n },\n refresh: function() {\n var optionIndex,\n element = this.element,\n options = element.options,\n value = this.bindings[VALUE].get(),\n values = value,\n field = this.options.valueField || this.options.textField,\n found = false,\n optionValue;\n\n if (!(values instanceof ObservableArray)) {\n values = new ObservableArray([value]);\n }\n\n element.selectedIndex = -1;\n\n for (var valueIndex = 0; valueIndex < values.length; valueIndex++) {\n value = values[valueIndex];\n\n if (field && value instanceof ObservableObject) {\n value = value.get(field);\n }\n\n for (optionIndex = 0; optionIndex < options.length; optionIndex++) {\n optionValue = options[optionIndex].value;\n\n if (optionValue === \"\" && value !== \"\") {\n optionValue = options[optionIndex].text;\n }\n\n if (optionValue == value) {\n options[optionIndex].selected = true;\n found = true;\n }\n }\n }\n },\n destroy: function() {\n $(this.element).off(CHANGE, this._change);\n }\n })\n };\n\n function dataSourceBinding(bindingName, fieldName, setter) {\n return Binder.extend({\n init: function(widget, bindings, options) {\n var that = this;\n\n Binder.fn.init.call(that, widget.element[0], bindings, options);\n\n that.widget = widget;\n that._dataBinding = proxy(that.dataBinding, that);\n that._dataBound = proxy(that.dataBound, that);\n that._itemChange = proxy(that.itemChange, that);\n },\n\n itemChange: function(e) {\n bindElement(e.item[0], e.data, this._ns(e.ns), [e.data].concat(this.bindings[bindingName]._parents()));\n },\n\n dataBinding: function(e) {\n var idx,\n length,\n widget = this.widget,\n items = e.removedItems || widget.items();\n\n for (idx = 0, length = items.length; idx < length; idx++) {\n unbindElementTree(items[idx]);\n }\n },\n\n _ns: function(ns) {\n ns = ns || kendo.ui;\n var all = [ kendo.ui, kendo.dataviz.ui, kendo.mobile.ui ];\n all.splice($.inArray(ns, all), 1);\n all.unshift(ns);\n\n return kendo.rolesFromNamespaces(all);\n },\n\n dataBound: function(e) {\n var idx,\n length,\n widget = this.widget,\n items = e.addedItems || widget.items(),\n dataSource = widget[fieldName],\n view,\n parents,\n groups = dataSource.group() || [];\n\n if (items.length) {\n view = e.addedDataItems || dataSource.flatView();\n parents = this.bindings[bindingName]._parents();\n\n for (idx = 0, length = view.length; idx < length; idx++) {\n bindElement(items[idx], view[idx], this._ns(e.ns), [view[idx]].concat(parents));\n }\n }\n },\n\n refresh: function(e) {\n var that = this,\n source,\n widget = that.widget;\n\n e = e || {};\n\n if (!e.action) {\n that.destroy();\n\n widget.bind(\"dataBinding\", that._dataBinding);\n widget.bind(\"dataBound\", that._dataBound);\n widget.bind(\"itemChange\", that._itemChange);\n\n source = that.bindings[bindingName].get();\n\n if (widget[fieldName] instanceof kendo.data.DataSource && widget[fieldName] != source) {\n if (source instanceof kendo.data.DataSource) {\n widget[setter](source);\n } else if (source && source._dataSource) {\n widget[setter](source._dataSource);\n } else {\n widget[fieldName].data(source);\n }\n }\n }\n },\n\n destroy: function() {\n var widget = this.widget;\n\n widget.unbind(\"dataBinding\", this._dataBinding);\n widget.unbind(\"dataBound\", this._dataBound);\n widget.unbind(\"itemChange\", this._itemChange);\n }\n });\n }\n\n binders.widget = {\n events : Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n this.widget = widget;\n this.handlers = {};\n },\n\n refresh: function(key) {\n var binding = this.bindings.events[key],\n handler = this.handlers[key];\n\n if (handler) {\n this.widget.unbind(key, handler);\n }\n\n handler = binding.get();\n\n this.handlers[key] = function(e) {\n e.data = binding.source;\n\n handler(e);\n\n if (e.data === binding.source) {\n delete e.data;\n }\n };\n\n this.widget.bind(key, this.handlers[key]);\n },\n\n destroy: function() {\n var handler;\n\n for (handler in this.handlers) {\n this.widget.unbind(handler, this.handlers[handler]);\n }\n }\n }),\n\n checked: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n this._change = proxy(this.change, this);\n this.widget.bind(CHANGE, this._change);\n },\n change: function() {\n this.bindings[CHECKED].set(this.value());\n },\n\n refresh: function() {\n this.widget.check(this.bindings[CHECKED].get() === true);\n },\n\n value: function() {\n var element = this.element,\n value = element.value;\n\n if (value == \"on\" || value == \"off\") {\n value = element.checked;\n }\n\n return value;\n },\n\n destroy: function() {\n this.widget.unbind(CHANGE, this._change);\n }\n }),\n\n visible: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n },\n\n refresh: function() {\n var visible = this.bindings.visible.get();\n this.widget.wrapper[0].style.display = visible ? \"\" : \"none\";\n }\n }),\n\n invisible: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n },\n\n refresh: function() {\n var invisible = this.bindings.invisible.get();\n this.widget.wrapper[0].style.display = invisible ? \"none\" : \"\";\n }\n }),\n\n enabled: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n },\n\n refresh: function() {\n if (this.widget.enable) {\n this.widget.enable(this.bindings.enabled.get());\n }\n }\n }),\n\n disabled: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n },\n\n refresh: function() {\n if (this.widget.enable) {\n this.widget.enable(!this.bindings.disabled.get());\n }\n }\n }),\n\n source: dataSourceBinding(\"source\", \"dataSource\", \"setDataSource\"),\n\n value: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n this._change = $.proxy(this.change, this);\n this.widget.first(CHANGE, this._change);\n\n var value = this.bindings.value.get();\n\n this._valueIsObservableObject = !options.valuePrimitive && (value == null || value instanceof ObservableObject);\n this._valueIsObservableArray = value instanceof ObservableArray;\n this._initChange = false;\n },\n\n change: function() {\n var value = this.widget.value(),\n field = this.options.dataValueField || this.options.dataTextField,\n isArray = toString.call(value) === \"[object Array]\",\n isObservableObject = this._valueIsObservableObject,\n valueIndex, valueLength, values = [],\n sourceItem, sourceValue,\n idx, length, source;\n\n this._initChange = true;\n\n if (field) {\n\n if (this.bindings.source) {\n source = this.bindings.source.get();\n }\n\n if (value === \"\" && (isObservableObject || this.options.valuePrimitive)) {\n value = null;\n } else {\n if (!source || source instanceof kendo.data.DataSource) {\n source = this.widget.dataSource.view();\n }\n\n if (isArray) {\n valueLength = value.length;\n values = value.slice(0);\n }\n\n for (idx = 0, length = source.length; idx < length; idx++) {\n sourceItem = source[idx];\n sourceValue = sourceItem.get(field);\n\n if (isArray) {\n for (valueIndex = 0; valueIndex < valueLength; valueIndex++) {\n if (sourceValue == values[valueIndex]) {\n values[valueIndex] = sourceItem;\n break;\n }\n }\n } else if (sourceValue == value) {\n value = isObservableObject ? sourceItem : sourceValue;\n break;\n }\n }\n\n if (values[0]) {\n if (this._valueIsObservableArray) {\n value = values;\n } else if (isObservableObject || !field) {\n value = values[0];\n } else {\n value = values[0].get(field);\n }\n }\n }\n }\n\n this.bindings.value.set(value);\n this._initChange = false;\n },\n\n refresh: function() {\n\n if (!this._initChange) {\n var field = this.options.dataValueField || this.options.dataTextField,\n value = this.bindings.value.get(),\n idx = 0, length,\n values = [];\n\n if (value === undefined) {\n value = null;\n }\n\n if (field) {\n if (value instanceof ObservableArray) {\n for (length = value.length; idx < length; idx++) {\n values[idx] = value[idx].get(field);\n }\n value = values;\n } else if (value instanceof ObservableObject) {\n value = value.get(field);\n }\n }\n this.widget.value(value);\n }\n\n this._initChange = false;\n },\n\n destroy: function() {\n this.widget.unbind(CHANGE, this._change);\n }\n }),\n\n gantt: {\n dependencies: dataSourceBinding(\"dependencies\", \"dependencies\", \"setDependenciesDataSource\")\n },\n\n multiselect: {\n value: Binder.extend({\n init: function(widget, bindings, options) {\n Binder.fn.init.call(this, widget.element[0], bindings, options);\n\n this.widget = widget;\n this._change = $.proxy(this.change, this);\n this.widget.first(CHANGE, this._change);\n this._initChange = false;\n },\n\n change: function() {\n var that = this,\n oldValues = that.bindings[VALUE].get(),\n valuePrimitive = that.options.valuePrimitive,\n newValues = valuePrimitive ? that.widget.value() : that.widget.dataItems();\n\n var field = this.options.dataValueField || this.options.dataTextField;\n\n newValues = newValues.slice(0);\n\n that._initChange = true;\n\n if (oldValues instanceof ObservableArray) {\n var remove = [];\n\n var newLength = newValues.length;\n\n var i = 0, j = 0;\n var old = oldValues[i];\n var same = false;\n var removeIndex;\n var newValue;\n var found;\n\n while (old) {\n found = false;\n for (j = 0; j < newLength; j++) {\n if (valuePrimitive) {\n same = newValues[j] == old;\n } else {\n newValue = newValues[j];\n\n newValue = newValue.get ? newValue.get(field) : newValue;\n same = newValue == (old.get ? old.get(field) : old);\n }\n\n if (same) {\n newValues.splice(j, 1);\n newLength -= 1;\n found = true;\n break;\n }\n }\n\n if (!found) {\n remove.push(old);\n arraySplice(oldValues, i, 1);\n removeIndex = i;\n } else {\n i += 1;\n }\n\n old = oldValues[i];\n }\n\n arraySplice(oldValues, oldValues.length, 0, newValues);\n\n if (remove.length) {\n oldValues.trigger(\"change\", {\n action: \"remove\",\n items: remove,\n index: removeIndex\n });\n }\n\n if (newValues.length) {\n oldValues.trigger(\"change\", {\n action: \"add\",\n items: newValues,\n index: oldValues.length - 1\n });\n }\n } else {\n that.bindings[VALUE].set(newValues);\n }\n\n that._initChange = false;\n },\n\n refresh: function() {\n if (!this._initChange) {\n var field = this.options.dataValueField || this.options.dataTextField,\n value = this.bindings.value.get(),\n idx = 0, length,\n values = [],\n selectedValue;\n\n if (value === undefined) {\n value = null;\n }\n\n if (field) {\n if (value instanceof ObservableArray) {\n for (length = value.length; idx < length; idx++) {\n selectedValue = value[idx];\n values[idx] = selectedValue.get ? selectedValue.get(field) : selectedValue;\n }\n value = values;\n } else if (value instanceof ObservableObject) {\n value = value.get(field);\n }\n }\n\n this.widget.value(value);\n }\n },\n\n destroy: function() {\n this.widget.unbind(CHANGE, this._change);\n }\n\n })\n }\n };\n\n var arraySplice = function(arr, idx, remove, add) {\n add = add || [];\n remove = remove || 0;\n\n var addLength = add.length;\n var oldLength = arr.length;\n\n var shifted = [].slice.call(arr, idx + remove);\n var shiftedLength = shifted.length;\n var index;\n\n if (addLength) {\n addLength = idx + addLength;\n index = 0;\n\n for (; idx < addLength; idx++) {\n arr[idx] = add[index];\n index++;\n }\n\n arr.length = addLength;\n } else if (remove) {\n arr.length = idx;\n\n remove += idx;\n while (idx < remove) {\n delete arr[--remove];\n }\n }\n\n if (shiftedLength) {\n shiftedLength = idx + shiftedLength;\n index = 0;\n\n for (; idx < shiftedLength; idx++) {\n arr[idx] = shifted[index];\n index++;\n }\n\n arr.length = shiftedLength;\n }\n\n idx = arr.length;\n\n while (idx < oldLength) {\n delete arr[idx];\n idx++;\n }\n };\n\n var BindingTarget = Class.extend( {\n init: function(target, options) {\n this.target = target;\n this.options = options;\n this.toDestroy = [];\n },\n\n bind: function(bindings) {\n var nodeName = this.target.nodeName.toLowerCase(),\n key,\n hasValue,\n hasSource,\n hasEvents,\n specificBinders = binders[nodeName] || {};\n\n for (key in bindings) {\n if (key == VALUE) {\n hasValue = true;\n } else if (key == SOURCE) {\n hasSource = true;\n } else if (key == EVENTS) {\n hasEvents = true;\n } else {\n this.applyBinding(key, bindings, specificBinders);\n }\n }\n\n if (hasSource) {\n this.applyBinding(SOURCE, bindings, specificBinders);\n }\n\n if (hasValue) {\n this.applyBinding(VALUE, bindings, specificBinders);\n }\n\n if (hasEvents) {\n this.applyBinding(EVENTS, bindings, specificBinders);\n }\n },\n\n applyBinding: function(name, bindings, specificBinders) {\n var binder = specificBinders[name] || binders[name],\n toDestroy = this.toDestroy,\n attribute,\n binding = bindings[name];\n\n if (binder) {\n binder = new binder(this.target, bindings, this.options);\n\n toDestroy.push(binder);\n\n if (binding instanceof Binding) {\n binder.bind(binding);\n toDestroy.push(binding);\n } else {\n for (attribute in binding) {\n binder.bind(binding, attribute);\n toDestroy.push(binding[attribute]);\n }\n }\n } else if (name !== \"template\") {\n throw new Error(\"The \" + name + \" binding is not supported by the \" + this.target.nodeName.toLowerCase() + \" element\");\n }\n },\n\n destroy: function() {\n var idx,\n length,\n toDestroy = this.toDestroy;\n\n for (idx = 0, length = toDestroy.length; idx < length; idx++) {\n toDestroy[idx].destroy();\n }\n }\n });\n\n var WidgetBindingTarget = BindingTarget.extend( {\n bind: function(bindings) {\n var that = this,\n binding,\n hasValue = false,\n hasSource = false,\n specificBinders = binders.widget[that.target.options.name.toLowerCase()] || {};\n\n for (binding in bindings) {\n if (binding == VALUE) {\n hasValue = true;\n } else if (binding == SOURCE) {\n hasSource = true;\n } else {\n that.applyBinding(binding, bindings, specificBinders);\n }\n }\n\n if (hasSource) {\n that.applyBinding(SOURCE, bindings, specificBinders);\n }\n\n if (hasValue) {\n that.applyBinding(VALUE, bindings, specificBinders);\n }\n },\n\n applyBinding: function(name, bindings, specificBinders) {\n var binder = specificBinders[name] || binders.widget[name],\n toDestroy = this.toDestroy,\n attribute,\n binding = bindings[name];\n\n if (binder) {\n binder = new binder(this.target, bindings, this.target.options);\n\n toDestroy.push(binder);\n\n\n if (binding instanceof Binding) {\n binder.bind(binding);\n toDestroy.push(binding);\n } else {\n for (attribute in binding) {\n binder.bind(binding, attribute);\n toDestroy.push(binding[attribute]);\n }\n }\n } else {\n throw new Error(\"The \" + name + \" binding is not supported by the \" + this.target.options.name + \" widget\");\n }\n }\n });\n\n function bindingTargetForRole(element, roles) {\n var widget = kendo.initWidget(element, {}, roles);\n\n if (widget) {\n return new WidgetBindingTarget(widget);\n }\n }\n\n var keyValueRegExp = /[A-Za-z0-9_\\-]+:(\\{([^}]*)\\}|[^,}]+)/g,\n whiteSpaceRegExp = /\\s/g;\n\n function parseBindings(bind) {\n var result = {},\n idx,\n length,\n token,\n colonIndex,\n key,\n value,\n tokens;\n\n tokens = bind.match(keyValueRegExp);\n\n for (idx = 0, length = tokens.length; idx < length; idx++) {\n token = tokens[idx];\n colonIndex = token.indexOf(\":\");\n\n key = token.substring(0, colonIndex);\n value = token.substring(colonIndex + 1);\n\n if (value.charAt(0) == \"{\") {\n value = parseBindings(value);\n }\n\n result[key] = value;\n }\n\n return result;\n }\n\n function createBindings(bindings, source, type) {\n var binding,\n result = {};\n\n for (binding in bindings) {\n result[binding] = new type(source, bindings[binding]);\n }\n\n return result;\n }\n\n function bindElement(element, source, roles, parents) {\n var role = element.getAttribute(\"data-\" + kendo.ns + \"role\"),\n idx,\n bind = element.getAttribute(\"data-\" + kendo.ns + \"bind\"),\n children = element.children,\n childrenCopy = [],\n deep = true,\n bindings,\n options = {},\n target;\n\n parents = parents || [source];\n\n if (role || bind) {\n unbindElement(element);\n }\n\n if (role) {\n target = bindingTargetForRole(element, roles);\n }\n\n if (bind) {\n bind = parseBindings(bind.replace(whiteSpaceRegExp, \"\"));\n\n if (!target) {\n options = kendo.parseOptions(element, {textField: \"\", valueField: \"\", template: \"\", valueUpdate: CHANGE, valuePrimitive: false, autoBind: true});\n options.roles = roles;\n target = new BindingTarget(element, options);\n }\n\n target.source = source;\n\n bindings = createBindings(bind, parents, Binding);\n\n if (options.template) {\n bindings.template = new TemplateBinding(parents, \"\", options.template);\n }\n\n if (bindings.click) {\n bind.events = bind.events || {};\n bind.events.click = bind.click;\n bindings.click.destroy();\n delete bindings.click;\n }\n\n if (bindings.source) {\n deep = false;\n }\n\n if (bind.attr) {\n bindings.attr = createBindings(bind.attr, parents, Binding);\n }\n\n if (bind.style) {\n bindings.style = createBindings(bind.style, parents, Binding);\n }\n\n if (bind.events) {\n bindings.events = createBindings(bind.events, parents, EventBinding);\n }\n\n target.bind(bindings);\n }\n\n if (target) {\n element.kendoBindingTarget = target;\n }\n\n if (deep && children) {\n // https://github.com/telerik/kendo/issues/1240 for the weirdness.\n for (idx = 0; idx < children.length; idx++) {\n childrenCopy[idx] = children[idx];\n }\n\n for (idx = 0; idx < childrenCopy.length; idx++) {\n bindElement(childrenCopy[idx], source, roles, parents);\n }\n }\n }\n\n function bind(dom, object) {\n var idx,\n length,\n node,\n roles = kendo.rolesFromNamespaces([].slice.call(arguments, 2));\n\n object = kendo.observable(object);\n dom = $(dom);\n\n for (idx = 0, length = dom.length; idx < length; idx++) {\n node = dom[idx];\n if (node.nodeType === 1) {\n bindElement(node, object, roles);\n }\n }\n }\n\n function unbindElement(element) {\n var bindingTarget = element.kendoBindingTarget;\n\n if (bindingTarget) {\n bindingTarget.destroy();\n\n if (deleteExpando) {\n delete element.kendoBindingTarget;\n } else if (element.removeAttribute) {\n element.removeAttribute(\"kendoBindingTarget\");\n } else {\n element.kendoBindingTarget = null;\n }\n }\n }\n\n function unbindElementTree(element) {\n unbindElement(element);\n\n unbindElementChildren(element);\n }\n\n function unbindElementChildren(element) {\n var children = element.children;\n\n if (children) {\n for (var idx = 0, length = children.length; idx < length; idx++) {\n unbindElementTree(children[idx]);\n }\n }\n }\n\n function unbind(dom) {\n var idx, length;\n\n dom = $(dom);\n\n for (idx = 0, length = dom.length; idx < length; idx++ ) {\n unbindElementTree(dom[idx]);\n }\n }\n\n function notify(widget, namespace) {\n var element = widget.element,\n bindingTarget = element[0].kendoBindingTarget;\n\n if (bindingTarget) {\n bind(element, bindingTarget.source, namespace);\n }\n }\n\n kendo.unbind = unbind;\n kendo.bind = bind;\n kendo.data.binders = binders;\n kendo.data.Binder = Binder;\n kendo.notify = notify;\n\n kendo.observable = function(object) {\n if (!(object instanceof ObservableObject)) {\n object = new ObservableObject(object);\n }\n\n return object;\n };\n\n kendo.observableHierarchy = function(array) {\n var dataSource = kendo.data.HierarchicalDataSource.create(array);\n\n function recursiveRead(data) {\n var i, children;\n\n for (i = 0; i < data.length; i++) {\n data[i]._initChildren();\n\n children = data[i].children;\n\n children.fetch();\n\n data[i].items = children.data();\n\n recursiveRead(data[i].items);\n }\n }\n\n dataSource.fetch();\n\n recursiveRead(dataSource.data());\n\n dataSource._data._dataSource = dataSource;\n\n return dataSource._data;\n };\n\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\", \"./kendo.binder\", \"./kendo.fx\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n Observable = kendo.Observable,\n SCRIPT = \"SCRIPT\",\n INIT = \"init\",\n SHOW = \"show\",\n HIDE = \"hide\",\n TRANSITION_START = \"transitionStart\",\n TRANSITION_END = \"transitionEnd\",\n\n ATTACH = \"attach\",\n DETACH = \"detach\",\n sizzleErrorRegExp = /unrecognized expression/;\n\n var View = Observable.extend({\n init: function(content, options) {\n var that = this;\n options = options || {};\n\n Observable.fn.init.call(that);\n that.content = content;\n that.id = kendo.guid();\n that.tagName = options.tagName || \"div\";\n that.model = options.model;\n that._wrap = options.wrap !== false;\n this._evalTemplate = options.evalTemplate || false;\n that._fragments = {};\n\n that.bind([ INIT, SHOW, HIDE, TRANSITION_START, TRANSITION_END ], options);\n },\n\n render: function(container) {\n var that = this,\n notInitialized = !that.element;\n\n // The order below matters - kendo.bind should happen when the element is in the DOM, and show should be triggered after init.\n\n if (notInitialized) {\n that.element = that._createElement();\n }\n\n if (container) {\n $(container).append(that.element);\n }\n\n if (notInitialized) {\n kendo.bind(that.element, that.model);\n that.trigger(INIT);\n }\n\n if (container) {\n that._eachFragment(ATTACH);\n that.trigger(SHOW);\n }\n\n return that.element;\n },\n\n clone: function(back) {\n return new ViewClone(this);\n },\n\n triggerBeforeShow: function() {\n return true;\n },\n\n showStart: function() {\n this.element.css(\"display\", \"\");\n },\n\n showEnd: function() {\n },\n\n hideStart: function() {\n },\n\n hideEnd: function() {\n this.hide();\n },\n\n beforeTransition: function(type){\n this.trigger(TRANSITION_START, { type: type });\n },\n\n afterTransition: function(type){\n this.trigger(TRANSITION_END, { type: type });\n },\n\n hide: function() {\n this._eachFragment(DETACH);\n this.element.detach();\n this.trigger(HIDE);\n },\n\n destroy: function() {\n var element = this.element;\n\n if (element) {\n kendo.unbind(element);\n kendo.destroy(element);\n element.remove();\n }\n },\n\n fragments: function(fragments) {\n $.extend(this._fragments, fragments);\n },\n\n _eachFragment: function(methodName) {\n for (var placeholder in this._fragments) {\n this._fragments[placeholder][methodName](this, placeholder);\n }\n },\n\n _createElement: function() {\n var that = this,\n wrapper = \"<\" + that.tagName + \" />\",\n element,\n content;\n\n try {\n content = $(document.getElementById(that.content) || that.content); // support passing id without #\n\n if (content[0].tagName === SCRIPT) {\n content = content.html();\n }\n } catch(e) {\n if (sizzleErrorRegExp.test(e.message)) {\n content = that.content;\n }\n }\n\n if (typeof content === \"string\") {\n content = content.replace(/^\\s+|\\s+$/g, '');\n if (that._evalTemplate) {\n content = kendo.template(content)(that.model || {});\n }\n\n element = $(wrapper).append(content);\n // drop the wrapper if asked - this seems like the easiest (although not very intuitive) way to avoid messing up templates with questionable content, like this one for instance:\n // \n if (!that._wrap) {\n element = element.contents();\n }\n } else {\n element = content;\n if (that._wrap) {\n element = element.wrapAll(wrapper).parent();\n }\n }\n\n return element;\n }\n });\n\n var ViewClone = kendo.Class.extend({\n init: function(view) {\n $.extend(this, {\n element: view.element.clone(true),\n transition: view.transition,\n id: view.id\n });\n\n view.element.parent().append(this.element);\n },\n\n hideStart: $.noop,\n\n hideEnd: function() {\n this.element.remove();\n },\n\n beforeTransition: $.noop,\n afterTransition: $.noop\n });\n\n var Layout = View.extend({\n init: function(content, options) {\n View.fn.init.call(this, content, options);\n this.containers = {};\n },\n\n container: function(selector) {\n var container = this.containers[selector];\n\n if (!container) {\n container = this._createContainer(selector);\n this.containers[selector] = container;\n }\n\n return container;\n },\n\n showIn: function(selector, view, transition) {\n this.container(selector).show(view, transition);\n },\n\n _createContainer: function(selector) {\n var root = this.render(),\n element = root.find(selector),\n container;\n\n if (!element.length && root.is(selector)) {\n if (root.is(selector)) {\n element = root;\n } else {\n\n throw new Error(\"can't find a container with the specified \" + selector + \" selector\");\n }\n }\n\n container = new ViewContainer(element);\n\n container.bind(\"accepted\", function(e) {\n e.view.render(element);\n });\n\n return container;\n }\n });\n\n var Fragment = View.extend({\n attach: function(view, placeholder) {\n view.element.find(placeholder).replaceWith(this.render());\n },\n\n detach: function() {\n }\n });\n\n var transitionRegExp = /^(\\w+)(:(\\w+))?( (\\w+))?$/;\n\n function parseTransition(transition) {\n if (!transition){\n return {};\n }\n\n var matches = transition.match(transitionRegExp) || [];\n\n return {\n type: matches[1],\n direction: matches[3],\n reverse: matches[5] === \"reverse\"\n };\n }\n\n var ViewContainer = Observable.extend({\n init: function(container) {\n Observable.fn.init.call(this);\n this.container = container;\n this.history = [];\n this.view = null;\n this.running = false;\n },\n\n after: function() {\n this.running = false;\n this.trigger(\"complete\", {view: this.view});\n this.trigger(\"after\");\n },\n\n end: function() {\n this.view.showEnd();\n this.previous.hideEnd();\n this.after();\n },\n\n show: function(view, transition, locationID) {\n if (!view.triggerBeforeShow()) {\n this.trigger(\"after\");\n return false;\n }\n\n locationID = locationID || view.id;\n\n var that = this,\n current = (view === that.view) ? view.clone() : that.view,\n history = that.history,\n previousEntry = history[history.length - 2] || {},\n back = previousEntry.id === locationID,\n // If explicit transition is set, it will be with highest priority\n // Next we will try using the history record transition or the view transition configuration\n theTransition = transition || ( back ? history[history.length - 1].transition : view.transition ),\n transitionData = parseTransition(theTransition);\n\n if (that.running) {\n that.effect.stop();\n }\n\n if (theTransition === \"none\") {\n theTransition = null;\n }\n\n that.trigger(\"accepted\", { view: view });\n that.view = view;\n that.previous = current;\n that.running = true;\n\n if (!back) {\n history.push({ id: locationID, transition: theTransition });\n } else {\n history.pop();\n }\n\n if (!current) {\n view.showStart();\n view.showEnd();\n that.after();\n return true;\n }\n\n current.hideStart();\n\n if (!theTransition || !kendo.effects.enabled) {\n view.showStart();\n that.end();\n } else {\n // hide the view element before init/show - prevents blinks on iPad\n // the replace effect will remove this class\n view.element.addClass(\"k-fx-hidden\");\n view.showStart();\n // do not reverse the explicit transition\n if (back && !transition) {\n transitionData.reverse = !transitionData.reverse;\n }\n\n that.effect = kendo.fx(view.element).replace(current.element, transitionData.type)\n .beforeTransition(function() {\n view.beforeTransition(\"show\");\n current.beforeTransition(\"hide\");\n })\n .afterTransition(function() {\n view.afterTransition(\"show\");\n current.afterTransition(\"hide\");\n })\n .direction(transitionData.direction)\n .setReverse(transitionData.reverse);\n\n that.effect.run().then(function() { that.end(); });\n }\n\n return true;\n }\n });\n\n kendo.ViewContainer = ViewContainer;\n kendo.Fragment = Fragment;\n kendo.Layout = Layout;\n kendo.View = View;\n kendo.ViewClone = ViewClone;\n\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\", \"./kendo.fx\", \"./kendo.mobile.scroller\", \"./kendo.view\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n mobile = kendo.mobile,\n ui = mobile.ui,\n attr = kendo.attr,\n Class = kendo.Class,\n Widget = ui.Widget,\n ViewClone = kendo.ViewClone,\n INIT = \"init\",\n UI_OVERLAY = '
    ',\n BEFORE_SHOW = \"beforeShow\",\n SHOW = \"show\",\n AFTER_SHOW = \"afterShow\",\n BEFORE_HIDE = \"beforeHide\",\n TRANSITION_END = \"transitionEnd\",\n TRANSITION_START = \"transitionStart\",\n HIDE = \"hide\",\n DESTROY = \"destroy\",\n Z_INDEX = \"z-index\",\n attrValue = kendo.attrValue,\n roleSelector = kendo.roleSelector;\n\n function initPopOvers(element) {\n var popovers = element.find(roleSelector(\"popover\")),\n idx, length,\n roles = ui.roles;\n\n for (idx = 0, length = popovers.length; idx < length; idx ++) {\n kendo.initWidget(popovers[idx], {}, roles);\n }\n }\n\n function preventScrollIfNotInput(e) {\n if (!kendo.triggeredByInput(e)) {\n e.preventDefault();\n }\n }\n\n var View = Widget.extend({\n init: function(element, options) {\n Widget.fn.init.call(this, element, options);\n\n\n this.params = {};\n\n $.extend(this, options);\n\n this.transition = this.transition || this.defaultTransition;\n\n this._id();\n this._layout();\n this._overlay();\n this._scroller();\n this._model();\n },\n\n events: [\n INIT,\n BEFORE_SHOW,\n SHOW,\n AFTER_SHOW,\n BEFORE_HIDE,\n HIDE,\n DESTROY,\n TRANSITION_START,\n TRANSITION_END\n ],\n\n options: {\n name: \"View\",\n title: \"\",\n reload: false,\n transition: \"\",\n defaultTransition: \"\",\n useNativeScrolling: false,\n stretch: false,\n zoom: false,\n model: null,\n modelScope: window,\n scroller: {},\n initWidgets: true\n },\n\n enable: function(enable) {\n if(typeof enable == \"undefined\") {\n enable = true;\n }\n\n if(enable) {\n this.overlay.hide();\n } else {\n this.overlay.show();\n }\n },\n\n destroy: function() {\n if (this.layout) {\n this.layout.detach(this);\n }\n\n this.trigger(DESTROY);\n\n Widget.fn.destroy.call(this);\n\n if (this.scroller) {\n this.scroller.destroy();\n }\n\n\n kendo.destroy(this.element);\n },\n\n purge: function() {\n this.destroy();\n this.element.remove();\n },\n\n triggerBeforeShow: function() {\n if (this.trigger(BEFORE_SHOW, { view: this })) {\n return false;\n }\n return true;\n },\n\n showStart: function() {\n var that = this;\n that.element.css(\"display\", \"\");\n\n if (!that.inited) {\n that.inited = true;\n that.trigger(INIT, {view: that});\n }\n\n if (that.layout) {\n that.layout.attach(that);\n }\n\n that._padIfNativeScrolling();\n that.trigger(SHOW, {view: that});\n kendo.resize(that.element);\n },\n\n showEnd: function() {\n this.trigger(AFTER_SHOW, {view: this});\n this._padIfNativeScrolling();\n },\n\n hideStart: function() {\n this.trigger(BEFORE_HIDE, {view: this});\n },\n\n hideEnd: function() {\n var that = this;\n that.element.hide();\n that.trigger(HIDE, {view: that});\n\n if (that.layout) {\n that.layout.trigger(HIDE, { view : that, layout: that.layout });\n }\n },\n\n beforeTransition: function(type){\n this.trigger(TRANSITION_START, { type: type });\n },\n\n afterTransition: function(type){\n this.trigger(TRANSITION_END, { type: type });\n },\n\n _padIfNativeScrolling: function() {\n if (mobile.appLevelNativeScrolling()) {\n var isAndroid = kendo.support.mobileOS && kendo.support.mobileOS.android,\n topContainer = isAndroid ? \"footer\" : \"header\",\n bottomContainer = isAndroid ? \"header\" : \"footer\";\n\n this.content.css({\n paddingTop: this[topContainer].height(),\n paddingBottom: this[bottomContainer].height()\n });\n }\n },\n\n contentElement: function() {\n var that = this;\n\n return that.options.stretch ? that.content : that.scrollerContent;\n },\n\n clone: function(back) {\n return new ViewClone(this);\n },\n\n _scroller: function() {\n var that = this;\n\n if (mobile.appLevelNativeScrolling()) {\n return;\n }\n if (that.options.stretch) {\n that.content.addClass(\"km-stretched-view\");\n } else {\n that.content.kendoMobileScroller($.extend(that.options.scroller, { zoom: that.options.zoom, useNative: that.options.useNativeScrolling }));\n\n that.scroller = that.content.data(\"kendoMobileScroller\");\n that.scrollerContent = that.scroller.scrollElement;\n }\n\n // prevent accidental address bar display when pulling the header\n if (kendo.support.kineticScrollNeeded) {\n $(that.element).on(\"touchmove\", \".km-header\", preventScrollIfNotInput);\n if (!that.options.useNativeScrolling) {\n $(that.element).on(\"touchmove\", \".km-content\", preventScrollIfNotInput);\n }\n }\n },\n\n _model: function() {\n var that = this,\n element = that.element,\n model = that.options.model;\n\n if (typeof model === \"string\") {\n model = kendo.getter(model)(that.options.modelScope);\n }\n\n that.model = model;\n\n initPopOvers(element);\n\n that.element.css(\"display\", \"\");\n if (that.options.initWidgets) {\n if (model) {\n kendo.bind(element, model, ui, kendo.ui, kendo.dataviz.ui);\n } else {\n mobile.init(element.children());\n }\n }\n that.element.css(\"display\", \"none\");\n },\n\n _id: function() {\n var element = this.element,\n idAttrValue = element.attr(\"id\") || \"\";\n\n this.id = attrValue(element, \"url\") || \"#\" + idAttrValue;\n\n if (this.id == \"#\") {\n this.id = kendo.guid();\n element.attr(\"id\", this.id);\n }\n },\n\n _layout: function() {\n var that = this,\n contentSelector = roleSelector(\"content\"),\n element = that.element;\n\n element.addClass(\"km-view\");\n\n that.header = element.children(roleSelector(\"header\")).addClass(\"km-header\");\n that.footer = element.children(roleSelector(\"footer\")).addClass(\"km-footer\");\n\n if (!element.children(contentSelector)[0]) {\n element.wrapInner(\"
    ');\n }\n\n that.content = element.children(roleSelector(\"content\"))\n .addClass(\"km-content\");\n\n that.element.prepend(that.header).append(that.footer);\n\n\n if (that.layout) {\n that.layout.setup(that);\n }\n },\n\n _overlay: function() {\n this.overlay = $(UI_OVERLAY).appendTo(this.element);\n }\n });\n\n function initWidgets(collection) {\n collection.each(function() {\n kendo.initWidget($(this), {}, ui.roles);\n });\n }\n\n var Layout = Widget.extend({\n init: function(element, options) {\n var that = this;\n Widget.fn.init.call(that, element, options);\n\n element = that.element;\n\n that.header = element.children(roleSelector(\"header\")).addClass(\"km-header\");\n that.footer = element.children(roleSelector(\"footer\")).addClass(\"km-footer\");\n that.elements = that.header.add(that.footer);\n\n initPopOvers(element);\n\n kendo.mobile.init(that.element.children());\n that.element.detach();\n that.trigger(INIT, {layout: that});\n },\n\n options: {\n name: \"Layout\"\n },\n\n events: [\n INIT,\n SHOW,\n HIDE\n ],\n\n setup: function(view) {\n if (!view.header[0]) { view.header = this.header; }\n if (!view.footer[0]) { view.footer = this.footer; }\n },\n\n detach: function(view) {\n var that = this;\n if (view.header === that.header && that.header[0]) {\n view.element.prepend(that.header.detach()[0].cloneNode(true));\n }\n\n if (view.footer === that.footer && that.footer.length) {\n view.element.append(that.footer.detach()[0].cloneNode(true));\n }\n },\n\n attach: function(view) {\n var that = this,\n previousView = that.currentView;\n\n if (previousView) {\n that.detach(previousView);\n }\n\n if (view.header === that.header) {\n that.header.detach();\n view.element.children(roleSelector(\"header\")).remove();\n view.element.prepend(that.header);\n }\n\n if (view.footer === that.footer) {\n that.footer.detach();\n view.element.children(roleSelector(\"footer\")).remove();\n view.element.append(that.footer);\n }\n\n that.trigger(SHOW, {layout: that, view: view});\n that.currentView = view;\n }\n });\n\n var Observable = kendo.Observable,\n bodyRegExp = /]*>(([\\u000a\\u000d\\u2028\\u2029]|.)*)<\\/body>/i,\n LOAD_START = \"loadStart\",\n LOAD_COMPLETE = \"loadComplete\",\n SHOW_START = \"showStart\",\n SAME_VIEW_REQUESTED = \"sameViewRequested\",\n VIEW_SHOW = \"viewShow\",\n AFTER = \"after\";\n\n var ViewEngine = Observable.extend({\n init: function(options) {\n var that = this,\n views,\n errorMessage,\n container;\n\n Observable.fn.init.call(that);\n\n $.extend(that, options);\n that.sandbox = $(\"
    \");\n container = that.container;\n\n views = that._hideViews(container);\n that.rootView = views.first();\n\n if (!that.rootView[0] && options.rootNeeded) {\n if (container[0] == kendo.mobile.application.element[0]) {\n errorMessage = 'Your kendo mobile application element does not contain any direct child elements with data-role=\"view\" attribute set. Make sure that you instantiate the mobile application using the correct container.';\n } else {\n errorMessage = 'Your pane element does not contain any direct child elements with data-role=\"view\" attribute set.';\n }\n throw new Error(errorMessage);\n }\n\n that.layouts = {};\n\n that.viewContainer = new kendo.ViewContainer(that.container);\n\n that.viewContainer.bind(\"accepted\", function(e) {\n e.view.params = that.params;\n });\n\n that.viewContainer.bind(\"complete\", function(e) {\n that.trigger(VIEW_SHOW, { view: e.view });\n });\n\n that.viewContainer.bind(AFTER, function(e) {\n that.trigger(AFTER);\n });\n\n that._setupLayouts(container);\n\n initWidgets(container.children(roleSelector(\"modalview drawer\")));\n },\n\n destroy: function() {\n kendo.destroy(this.container);\n\n for (var id in this.layouts) {\n this.layouts[id].destroy();\n }\n },\n\n view: function() {\n return this.viewContainer.view;\n },\n\n showView: function(url, transition, params) {\n url = url.replace(new RegExp(\"^\" + this.remoteViewURLPrefix), \"\");\n if (url === \"\" && this.remoteViewURLPrefix) {\n url = \"/\";\n }\n\n if (url === this.url) {\n this.trigger(SAME_VIEW_REQUESTED);\n return false;\n }\n\n this.trigger(SHOW_START);\n\n var that = this,\n showClosure = function(view) {\n return that.viewContainer.show(view, transition, url);\n },\n element = that._findViewElement(url),\n view = kendo.widgetInstance(element);\n\n that.url = url;\n that.params = params;\n\n if (view && view.reload) {\n view.purge();\n element = [];\n }\n\n this.trigger(\"viewTypeDetermined\", { remote: element.length === 0, url: url });\n\n if (element[0]) {\n if (!view) {\n view = that._createView(element);\n }\n\n return showClosure(view);\n } else {\n that._loadView(url, showClosure);\n return true;\n }\n },\n\n append: function(html, url) {\n var that = this,\n sandbox = that.sandbox,\n urlPath = (url || \"\").split(\"?\")[0],\n container = that.container,\n views,\n modalViews,\n view;\n\n if (bodyRegExp.test(html)) {\n html = RegExp.$1;\n }\n\n sandbox[0].innerHTML = html;\n\n container.append(sandbox.children(\"script, style\"));\n\n views = that._hideViews(sandbox);\n view = views.first();\n\n // Generic HTML content found as remote view - no remote view markers\n if (!view.length) {\n views = view = sandbox.wrapInner(\"
    \").children(); // one element\n }\n\n if (urlPath) {\n view.hide().attr(attr(\"url\"), urlPath);\n }\n\n that._setupLayouts(sandbox);\n\n modalViews = sandbox.children(roleSelector(\"modalview drawer\"));\n\n container.append(sandbox.children(roleSelector(\"layout modalview drawer\")).add(views));\n\n // Initialize the modalviews after they have been appended to the final container\n initWidgets(modalViews);\n\n return that._createView(view);\n },\n\n\n _findViewElement: function(url) {\n var element,\n urlPath = url.split(\"?\")[0];\n\n if (!urlPath) {\n return this.rootView;\n }\n\n element = this.container.children(\"[\" + attr(\"url\") + \"='\" + urlPath + \"']\");\n\n // do not try to search for \"#/foo/bar\" id, jQuery throws error\n if (!element[0] && urlPath.indexOf(\"/\") === -1) {\n element = this.container.children(urlPath.charAt(0) === \"#\" ? urlPath : \"#\" + urlPath);\n }\n\n return element;\n },\n\n _createView: function(element) {\n var that = this,\n viewOptions,\n layout = attrValue(element, \"layout\");\n\n if (typeof layout === \"undefined\") {\n layout = that.layout;\n }\n\n if (layout) {\n layout = that.layouts[layout];\n }\n\n viewOptions = {\n defaultTransition: that.transition,\n loader: that.loader,\n container: that.container,\n layout: layout,\n modelScope: that.modelScope,\n reload: attrValue(element, \"reload\")\n };\n\n return kendo.initWidget(element, viewOptions, ui.roles);\n },\n\n _loadView: function(url, callback) {\n var that = this;\n\n if (this.serverNavigation) {\n location.href = url;\n return;\n }\n\n if (that._xhr) {\n that._xhr.abort();\n }\n\n that.trigger(LOAD_START);\n\n that._xhr = $.get(kendo.absoluteURL(url, that.remoteViewURLPrefix), function(html) {\n that.trigger(LOAD_COMPLETE);\n callback(that.append(html, url));\n }, 'html')\n .fail(function(request) {\n that.trigger(LOAD_COMPLETE);\n if (request.status === 0 && request.responseText) {\n callback(that.append(request.responseText, url));\n }\n });\n },\n\n _hideViews: function(container) {\n return container.children(roleSelector(\"view splitview\")).hide();\n },\n\n _setupLayouts: function(element) {\n var that = this;\n\n element.children(roleSelector(\"layout\")).each(function() {\n var layout = $(this),\n platform = attrValue(layout, \"platform\");\n\n if (platform === undefined || platform === mobile.application.os.name) {\n that.layouts[kendo.attrValue(layout, \"id\")] = kendo.initWidget(layout, {}, ui.roles);\n }\n });\n }\n });\n\n kendo.mobile.ViewEngine = ViewEngine;\n\n ui.plugin(View);\n ui.plugin(Layout);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n ui = kendo.mobile.ui,\n Widget = ui.Widget,\n CAPTURE_EVENTS = $.map(kendo.eventMap, function(value) { return value; }).join(\" \").split(\" \");\n\n var Loader = Widget.extend({\n init: function(container, options) {\n var that = this,\n element = $('
    ');\n\n Widget.fn.init.call(that, element, options);\n\n that.container = container;\n that.captureEvents = false;\n\n that._attachCapture();\n\n element.append(that.options.loading).hide().appendTo(container);\n },\n\n options: {\n name: \"Loader\",\n loading: \"

    Loading...

    \",\n timeout: 100\n },\n\n show: function() {\n var that = this;\n\n clearTimeout(that._loading);\n\n if (that.options.loading === false) {\n return;\n }\n\n that.captureEvents = true;\n that._loading = setTimeout(function() {\n that.element.show();\n }, that.options.timeout);\n },\n\n hide: function() {\n this.captureEvents = false;\n clearTimeout(this._loading);\n this.element.hide();\n },\n\n changeMessage: function(message) {\n this.options.loading = message;\n this.element.find(\">h1\").html(message);\n },\n\n transition: function() {\n this.captureEvents = true;\n this.container.css(\"pointer-events\", \"none\");\n },\n\n transitionDone: function() {\n this.captureEvents = false;\n this.container.css(\"pointer-events\", \"\");\n },\n\n _attachCapture: function() {\n var that = this;\n that.captureEvents = false;\n\n function capture(e) {\n if (that.captureEvents) {\n e.preventDefault();\n }\n }\n\n for (var i = 0; i < CAPTURE_EVENTS.length; i ++) {\n that.container[0].addEventListener(CAPTURE_EVENTS[i], capture, true);\n }\n }\n });\n\n ui.plugin(Loader);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.mobile.view\", \"./kendo.mobile.loader\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n mobile = kendo.mobile,\n roleSelector = kendo.roleSelector,\n ui = mobile.ui,\n Widget = ui.Widget,\n ViewEngine = mobile.ViewEngine,\n View = ui.View,\n Loader = mobile.ui.Loader,\n\n EXTERNAL = \"external\",\n HREF = \"href\",\n DUMMY_HREF = \"#!\",\n\n NAVIGATE = \"navigate\",\n VIEW_SHOW = \"viewShow\",\n SAME_VIEW_REQUESTED = \"sameViewRequested\",\n OS = kendo.support.mobileOS,\n SKIP_TRANSITION_ON_BACK_BUTTON = OS.ios && !OS.appMode && OS.flatVersion >= 700,\n\n WIDGET_RELS = /popover|actionsheet|modalview|drawer/,\n BACK = \"#:back\",\n\n attrValue = kendo.attrValue,\n // navigation element roles\n buttonRoles = \"button backbutton detailbutton listview-link\",\n linkRoles = \"tab\";\n\n var Pane = Widget.extend({\n init: function(element, options) {\n var that = this;\n\n Widget.fn.init.call(that, element, options);\n\n options = that.options;\n element = that.element;\n\n element.addClass(\"km-pane\");\n\n if (that.options.collapsible) {\n element.addClass(\"km-collapsible-pane\");\n }\n\n this.history = [];\n\n this.historyCallback = function(url, params, backButtonPressed) {\n var transition = that.transition;\n that.transition = null;\n\n // swiping back in iOS leaves the app in a very broken state if we perform a transition\n if (SKIP_TRANSITION_ON_BACK_BUTTON && backButtonPressed) {\n transition = \"none\";\n }\n\n return that.viewEngine.showView(url, transition, params);\n };\n\n this._historyNavigate = function(url) {\n if (url === BACK) {\n if (that.history.length === 1) {\n return;\n }\n\n that.history.pop();\n url = that.history[that.history.length - 1];\n } else {\n that.history.push(url);\n }\n\n that.historyCallback(url, kendo.parseQueryStringParams(url));\n };\n\n this._historyReplace = function(url) {\n var params = kendo.parseQueryStringParams(url);\n that.history[that.history.length - 1] = url;\n that.historyCallback(url, params);\n };\n\n that.loader = new Loader(element, {\n loading: that.options.loading\n });\n\n that.viewEngine = new ViewEngine({\n container: element,\n transition: options.transition,\n modelScope: options.modelScope,\n rootNeeded: !options.initial,\n serverNavigation: options.serverNavigation,\n remoteViewURLPrefix: options.root || \"\",\n layout: options.layout,\n loader: that.loader\n });\n\n that.viewEngine.bind(\"showStart\", function() {\n that.loader.transition();\n that.closeActiveDialogs();\n });\n\n that.viewEngine.bind(\"after\", function(e) {\n that.loader.transitionDone();\n });\n\n that.viewEngine.bind(VIEW_SHOW, function(e) {\n that.trigger(VIEW_SHOW, e);\n });\n\n that.viewEngine.bind(\"loadStart\", function() {\n that.loader.show();\n });\n\n that.viewEngine.bind(\"loadComplete\", function() {\n that.loader.hide();\n });\n\n that.viewEngine.bind(SAME_VIEW_REQUESTED, function() {\n that.trigger(SAME_VIEW_REQUESTED);\n });\n\n that.viewEngine.bind(\"viewTypeDetermined\", function(e) {\n if (!e.remote || !that.options.serverNavigation) {\n that.trigger(NAVIGATE, { url: e.url });\n }\n });\n\n this._setPortraitWidth();\n\n kendo.onResize(function() {\n that._setPortraitWidth();\n });\n\n that._setupAppLinks();\n },\n\n closeActiveDialogs: function() {\n var dialogs = this.element.find(roleSelector(\"actionsheet popover modalview\")).filter(\":visible\");\n dialogs.each(function() {\n kendo.widgetInstance($(this), ui).close();\n });\n },\n\n navigateToInitial: function() {\n var initial = this.options.initial;\n\n if (initial) {\n this.navigate(initial);\n }\n },\n\n options: {\n name: \"Pane\",\n portraitWidth: \"\",\n transition: \"\",\n layout: \"\",\n collapsible: false,\n initial: null,\n modelScope: window,\n loading: \"

    Loading...

    \"\n },\n\n events: [\n NAVIGATE,\n VIEW_SHOW,\n SAME_VIEW_REQUESTED\n ],\n\n append: function(html) {\n return this.viewEngine.append(html);\n },\n\n destroy: function() {\n Widget.fn.destroy.call(this);\n this.viewEngine.destroy();\n this.userEvents.destroy();\n },\n\n navigate: function(url, transition) {\n if (url instanceof View) {\n url = url.id;\n }\n\n this.transition = transition;\n\n this._historyNavigate(url);\n },\n\n replace: function(url, transition) {\n if (url instanceof View) {\n url = url.id;\n }\n\n this.transition = transition;\n\n this._historyReplace(url);\n },\n\n bindToRouter: function(router) {\n var that = this,\n options = that.options,\n initial = options.initial,\n viewEngine = this.viewEngine;\n\n router.bind(\"init\", function(e) {\n var url = e.url,\n attrUrl = router.pushState ? url : \"/\";\n\n viewEngine.rootView.attr(kendo.attr(\"url\"), attrUrl);\n\n if (url === \"/\" && initial) {\n router.navigate(initial, true);\n e.preventDefault(); // prevents from executing routeMissing, by default\n }\n });\n\n router.bind(\"routeMissing\", function(e) {\n if (!that.historyCallback(e.url, e.params, e.backButtonPressed)) {\n e.preventDefault();\n }\n });\n\n router.bind(\"same\", function() {\n that.trigger(SAME_VIEW_REQUESTED);\n });\n\n that._historyNavigate = function(url) {\n router.navigate(url);\n };\n\n that._historyReplace = function(url) {\n router.replace(url);\n };\n },\n\n hideLoading: function() {\n this.loader.hide();\n },\n\n showLoading: function() {\n this.loader.show();\n },\n\n changeLoadingMessage: function(message) {\n this.loader.changeMessage(message);\n },\n\n view: function() {\n return this.viewEngine.view();\n },\n\n _setPortraitWidth: function() {\n var width,\n portraitWidth = this.options.portraitWidth;\n\n if (portraitWidth) {\n width = kendo.mobile.application.element.is(\".km-vertical\") ? portraitWidth : \"auto\";\n this.element.css(\"width\", width);\n }\n },\n\n _setupAppLinks: function() {\n var that = this;\n this.element.handler(this)\n .on(\"down\", roleSelector(linkRoles), \"_mouseup\")\n .on(\"click\", roleSelector(linkRoles + \" \" + buttonRoles), \"_appLinkClick\");\n\n this.userEvents = new kendo.UserEvents(this.element, {\n filter: roleSelector(buttonRoles),\n tap: function(e) {\n e.event.currentTarget = e.touch.currentTarget;\n that._mouseup(e.event);\n }\n });\n },\n\n _appLinkClick: function (e) {\n var href = $(e.currentTarget).attr(\"href\");\n var remote = href && href[0] !== \"#\" && this.options.serverNavigation;\n\n if(!remote && attrValue($(e.currentTarget), \"rel\") != EXTERNAL) {\n e.preventDefault();\n }\n },\n\n _mouseup: function(e) {\n if (e.which > 1 || e.isDefaultPrevented()) {\n return;\n }\n\n var pane = this,\n link = $(e.currentTarget),\n transition = attrValue(link, \"transition\"),\n rel = attrValue(link, \"rel\") || \"\",\n target = attrValue(link, \"target\"),\n href = link.attr(HREF),\n delayedTouchEnd = SKIP_TRANSITION_ON_BACK_BUTTON && link[0].offsetHeight === 0,\n remote = href && href[0] !== \"#\" && this.options.serverNavigation;\n\n if (delayedTouchEnd || remote || rel === EXTERNAL || (typeof href === \"undefined\") || href === DUMMY_HREF) {\n return;\n }\n\n // Prevent iOS address bar progress display for in app navigation\n link.attr(HREF, DUMMY_HREF);\n setTimeout(function() { link.attr(HREF, href); });\n\n if (rel.match(WIDGET_RELS)) {\n kendo.widgetInstance($(href), ui).openFor(link);\n // if propagation is not stopped and actionsheet is opened from tabstrip,\n // the actionsheet is closed immediately.\n if (rel === \"actionsheet\" || rel === \"drawer\") {\n e.stopPropagation();\n }\n } else {\n if (target === \"_top\") {\n pane = mobile.application.pane;\n }\n else if (target) {\n pane = $(\"#\" + target).data(\"kendoMobilePane\");\n }\n\n pane.navigate(href, transition);\n }\n\n e.preventDefault();\n }\n });\n\n Pane.wrap = function(element) {\n if (!element.is(roleSelector(\"view\"))) {\n element = element.wrap('
    ').parent();\n }\n\n var paneContainer = element.wrap('
    ').parent(),\n pane = new Pane(paneContainer);\n\n pane.navigate(\"\");\n\n return pane;\n };\n ui.plugin(Pane);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n CHANGE = \"change\",\n BACK = \"back\",\n SAME = \"same\",\n support = kendo.support,\n location = window.location,\n history = window.history,\n CHECK_URL_INTERVAL = 50,\n BROKEN_BACK_NAV = kendo.support.browser.msie,\n hashStrip = /^#*/,\n document = window.document;\n\n function absoluteURL(path, pathPrefix) {\n if (!pathPrefix) {\n return path;\n }\n\n if (path + \"/\" === pathPrefix) {\n path = pathPrefix;\n }\n\n var regEx = new RegExp(\"^\" + pathPrefix, \"i\");\n\n if (!regEx.test(path)) {\n path = pathPrefix + \"/\" + path;\n }\n\n return location.protocol + '//' + (location.host + \"/\" + path).replace(/\\/\\/+/g, '/');\n }\n\n function hashDelimiter(bang) {\n return bang ? \"#!\" : \"#\";\n }\n\n function locationHash(hashDelimiter) {\n var href = location.href;\n\n // ignore normal anchors if in hashbang mode - however, still return \"\" if no hash present\n if (hashDelimiter === \"#!\" && href.indexOf(\"#\") > -1 && href.indexOf(\"#!\") < 0) {\n return null;\n }\n\n return href.split(hashDelimiter)[1] || \"\";\n }\n\n function stripRoot(root, url) {\n if (url.indexOf(root) === 0) {\n return (url.substr(root.length)).replace(/\\/\\//g, '/');\n } else {\n return url;\n }\n }\n\n var HistoryAdapter = kendo.Class.extend({\n back: function() {\n if (BROKEN_BACK_NAV) {\n setTimeout(function() { history.back(); });\n } else {\n history.back();\n }\n },\n\n forward: function() {\n if (BROKEN_BACK_NAV) {\n setTimeout(function() { history.forward(); });\n } else {\n history.forward();\n }\n },\n\n length: function() {\n return history.length;\n },\n\n replaceLocation: function(url) {\n location.replace(url);\n }\n });\n\n var PushStateAdapter = HistoryAdapter.extend({\n init: function(root) {\n this.root = root;\n },\n\n navigate: function(to) {\n history.pushState({}, document.title, absoluteURL(to, this.root));\n },\n\n replace: function(to) {\n history.replaceState({}, document.title, absoluteURL(to, this.root));\n },\n\n normalize: function(url) {\n return stripRoot(this.root, url);\n },\n\n current: function() {\n var current = location.pathname;\n\n if (location.search) {\n current += location.search;\n }\n\n return stripRoot(this.root, current);\n },\n\n change: function(callback) {\n $(window).bind(\"popstate.kendo\", callback);\n },\n\n stop: function() {\n $(window).unbind(\"popstate.kendo\");\n },\n\n normalizeCurrent: function(options) {\n var fixedUrl,\n root = options.root,\n pathname = location.pathname,\n hash = locationHash(hashDelimiter(options.hashBang));\n\n if (root === pathname + \"/\") {\n fixedUrl = root;\n }\n\n if (root === pathname && hash) {\n fixedUrl = absoluteURL(hash.replace(hashStrip, ''), root);\n }\n\n if (fixedUrl) {\n history.pushState({}, document.title, fixedUrl);\n }\n }\n });\n\n function fixHash(url) {\n return url.replace(/^(#)?/, \"#\");\n }\n\n function fixBang(url) {\n return url.replace(/^(#(!)?)?/, \"#!\");\n }\n\n var HashAdapter = HistoryAdapter.extend({\n init: function(bang) {\n this._id = kendo.guid();\n this.prefix = hashDelimiter(bang);\n this.fix = bang ? fixBang : fixHash;\n },\n\n navigate: function(to) {\n location.hash = this.fix(to);\n },\n\n replace: function(to) {\n this.replaceLocation(this.fix(to));\n },\n\n normalize: function(url) {\n if (url.indexOf(this.prefix) < 0) {\n return url;\n } else {\n return url.split(this.prefix)[1];\n }\n },\n\n change: function(callback) {\n if (support.hashChange) {\n $(window).on(\"hashchange.\" + this._id, callback);\n } else {\n this._interval = setInterval(callback, CHECK_URL_INTERVAL);\n }\n },\n\n stop: function() {\n $(window).off(\"hashchange.\" + this._id);\n clearInterval(this._interval);\n },\n\n current: function() {\n return locationHash(this.prefix);\n },\n\n normalizeCurrent: function(options) {\n var pathname = location.pathname,\n root = options.root;\n\n if (options.pushState && root !== pathname) {\n this.replaceLocation(root + this.prefix + stripRoot(root, pathname));\n return true; // browser will reload at this point.\n }\n\n return false;\n }\n });\n\n var History = kendo.Observable.extend({\n start: function(options) {\n options = options || {};\n\n this.bind([CHANGE, BACK, SAME], options);\n\n if (this._started) {\n return;\n }\n\n this._started = true;\n\n options.root = options.root || \"/\";\n\n var adapter = this.createAdapter(options),\n current;\n\n // adapter may reload the document\n if (adapter.normalizeCurrent(options)) {\n return;\n }\n\n current = adapter.current();\n\n $.extend(this, {\n adapter: adapter,\n root: options.root,\n historyLength: adapter.length(),\n current: current,\n locations: [current]\n });\n\n adapter.change($.proxy(this, \"_checkUrl\"));\n },\n\n createAdapter:function(options) {\n return support.pushState && options.pushState ? new PushStateAdapter(options.root) : new HashAdapter(options.hashBang);\n },\n\n stop: function() {\n if (!this._started) {\n return;\n }\n this.adapter.stop();\n this.unbind(CHANGE);\n this._started = false;\n },\n\n change: function(callback) {\n this.bind(CHANGE, callback);\n },\n\n replace: function(to, silent) {\n\n this._navigate(to, silent, function(adapter) {\n adapter.replace(to);\n this.locations[this.locations - 1] = this.current;\n });\n },\n\n navigate: function(to, silent) {\n if (to === \"#:back\") {\n this.backCalled = true;\n this.adapter.back();\n return;\n }\n\n this._navigate(to, silent, function(adapter) {\n adapter.navigate(to);\n this.locations.push(this.current);\n });\n },\n\n _navigate: function(to, silent, callback) {\n var adapter = this.adapter;\n\n to = adapter.normalize(to);\n\n if (this.current === to || this.current === decodeURIComponent(to)) {\n this.trigger(SAME);\n return;\n }\n\n if (!silent) {\n if (this.trigger(CHANGE, { url: to })) {\n return;\n }\n }\n\n this.current = to;\n\n callback.call(this, adapter);\n\n this.historyLength = adapter.length();\n },\n\n _checkUrl: function() {\n var adapter = this.adapter,\n current = adapter.current(),\n newLength = adapter.length(),\n navigatingInExisting = this.historyLength === newLength,\n back = current === this.locations[this.locations.length - 2] && navigatingInExisting,\n backCalled = this.backCalled,\n prev = this.current;\n\n if (current === null || this.current === current || this.current === decodeURIComponent(current)) {\n return true;\n }\n\n this.historyLength = newLength;\n this.backCalled = false;\n\n this.current = current;\n\n if (back && this.trigger(\"back\", { url: prev, to: current })) {\n adapter.forward();\n this.current = prev;\n return;\n }\n\n if (this.trigger(CHANGE, { url: current, backButtonPressed: !backCalled })) {\n if (back) {\n adapter.forward();\n } else {\n adapter.back();\n this.historyLength --;\n }\n this.current = prev;\n return;\n }\n\n if (back) {\n this.locations.pop();\n } else {\n this.locations.push(current);\n }\n }\n });\n\n kendo.History = History;\n kendo.History.HistoryAdapter = HistoryAdapter;\n kendo.History.HashAdapter = HashAdapter;\n kendo.History.PushStateAdapter = PushStateAdapter;\n kendo.absoluteURL = absoluteURL;\n kendo.history = new History();\n})(window.kendo.jQuery);\n\n(function() {\n var kendo = window.kendo,\n history = kendo.history,\n Observable = kendo.Observable,\n INIT = \"init\",\n ROUTE_MISSING = \"routeMissing\",\n CHANGE = \"change\",\n BACK = \"back\",\n SAME = \"same\",\n optionalParam = /\\((.*?)\\)/g,\n namedParam = /(\\(\\?)?:\\w+/g,\n splatParam = /\\*\\w+/g,\n escapeRegExp = /[\\-{}\\[\\]+?.,\\\\\\^$|#\\s]/g;\n\n function namedParamReplace(match, optional) {\n return optional ? match : '([^\\/]+)';\n }\n\n function routeToRegExp(route) {\n return new RegExp('^' + route\n .replace(escapeRegExp, '\\\\$&')\n .replace(optionalParam, '(?:$1)?')\n .replace(namedParam, namedParamReplace)\n .replace(splatParam, '(.*?)') + '$');\n }\n\n function stripUrl(url) {\n return url.replace(/(\\?.*)|(#.*)/g, \"\");\n }\n\n var Route = kendo.Class.extend({\n init: function(route, callback) {\n if (!(route instanceof RegExp)) {\n route = routeToRegExp(route);\n }\n\n this.route = route;\n this._callback = callback;\n },\n\n callback: function(url) {\n var params,\n idx = 0,\n length,\n queryStringParams = kendo.parseQueryStringParams(url);\n\n url = stripUrl(url);\n params = this.route.exec(url).slice(1);\n length = params.length;\n\n for (; idx < length; idx ++) {\n if (typeof params[idx] !== 'undefined') {\n params[idx] = decodeURIComponent(params[idx]);\n }\n }\n\n params.push(queryStringParams);\n\n this._callback.apply(null, params);\n },\n\n worksWith: function(url) {\n if (this.route.test(stripUrl(url))) {\n this.callback(url);\n return true;\n } else {\n return false;\n }\n }\n });\n\n var Router = Observable.extend({\n init: function(options) {\n if (!options) {\n options = {};\n }\n\n Observable.fn.init.call(this);\n\n this.routes = [];\n this.pushState = options.pushState;\n this.hashBang = options.hashBang;\n this.root = options.root;\n\n this.bind([INIT, ROUTE_MISSING, CHANGE, SAME], options);\n },\n\n destroy: function() {\n history.unbind(CHANGE, this._urlChangedProxy);\n history.unbind(SAME, this._sameProxy);\n history.unbind(BACK, this._backProxy);\n this.unbind();\n },\n\n start: function() {\n var that = this,\n sameProxy = function() { that._same(); },\n backProxy = function(e) { that._back(e); },\n urlChangedProxy = function(e) { that._urlChanged(e); };\n\n history.start({\n same: sameProxy,\n change: urlChangedProxy,\n back: backProxy,\n pushState: that.pushState,\n hashBang: that.hashBang,\n root: that.root\n });\n\n var initEventObject = { url: history.current || \"/\", preventDefault: $.noop };\n\n if (!that.trigger(INIT, initEventObject)) {\n that._urlChanged(initEventObject);\n }\n\n this._urlChangedProxy = urlChangedProxy;\n this._backProxy = backProxy;\n },\n\n route: function(route, callback) {\n this.routes.push(new Route(route, callback));\n },\n\n navigate: function(url, silent) {\n kendo.history.navigate(url, silent);\n },\n\n replace: function(url, silent) {\n kendo.history.replace(url, silent);\n },\n\n _back: function(e) {\n if (this.trigger(BACK, { url: e.url, to: e.to })) {\n e.preventDefault();\n }\n },\n\n _same: function(e) {\n this.trigger(SAME);\n },\n\n _urlChanged: function(e) {\n var url = e.url;\n\n if (!url) {\n url = \"/\";\n }\n\n if (this.trigger(CHANGE, { url: e.url, params: kendo.parseQueryStringParams(e.url), backButtonPressed: e.backButtonPressed })) {\n e.preventDefault();\n return;\n }\n\n var idx = 0,\n routes = this.routes,\n route,\n length = routes.length;\n\n for (; idx < length; idx ++) {\n route = routes[idx];\n\n if (route.worksWith(url)) {\n return;\n }\n }\n\n if (this.trigger(ROUTE_MISSING, { url: url, params: kendo.parseQueryStringParams(url), backButtonPressed: e.backButtonPressed })) {\n e.preventDefault();\n }\n }\n });\n\n kendo.Router = Router;\n})();\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.mobile.pane\", \"./kendo.router\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n mobile = kendo.mobile,\n support = kendo.support,\n Pane = mobile.ui.Pane,\n\n DEFAULT_OS = \"ios7\",\n OS = support.mobileOS,\n BERRYPHONEGAP = OS.device == \"blackberry\" && OS.flatVersion >= 600 && OS.flatVersion < 1000 && OS.appMode,\n VERTICAL = \"km-vertical\",\n CHROME = OS.browser === \"chrome\",\n BROKEN_WEBVIEW_RESIZE = OS.ios && OS.flatVersion >= 700 && (OS.appMode || CHROME),\n INITIALLY_HORIZONTAL = (Math.abs(window.orientation) / 90 == 1),\n HORIZONTAL = \"km-horizontal\",\n\n MOBILE_PLATFORMS = {\n ios7: { ios: true, browser: \"default\", device: \"iphone\", flatVersion: \"700\", majorVersion: \"7\", minorVersion: \"0.0\", name: \"ios\", tablet: false },\n ios: { ios: true, browser: \"default\", device: \"iphone\", flatVersion: \"612\", majorVersion: \"6\", minorVersion: \"1.2\", name: \"ios\", tablet: false },\n android: { android: true, browser: \"default\", device: \"android\", flatVersion: \"442\", majorVersion: \"4\", minorVersion: \"4.2\", name: \"android\", tablet: false },\n blackberry: { blackberry: true, browser: \"default\", device: \"blackberry\", flatVersion: \"710\", majorVersion: \"7\", minorVersion: \"1.0\", name: \"blackberry\", tablet: false },\n meego: { meego: true, browser: \"default\", device: \"meego\", flatVersion: \"850\", majorVersion: \"8\", minorVersion: \"5.0\", name: \"meego\", tablet: false },\n wp: { wp: true, browser: \"default\", device: \"wp\", flatVersion: \"800\", majorVersion: \"8\", minorVersion: \"0.0\", name: \"wp\", tablet: false }\n },\n\n viewportTemplate = kendo.template('', {usedWithBlock: false}),\n systemMeta = kendo.template(' ' +\n ' ' +\n ' ', {usedWithBlock: false}),\n clipTemplate = kendo.template('', {usedWithBlock: false}),\n ENABLE_CLIP = OS.android && OS.browser != \"chrome\" || OS.blackberry,\n viewportMeta = viewportTemplate({ height: \"\" }),\n\n iconMeta = kendo.template('', {usedWithBlock: false}),\n\n HIDEBAR = (OS.device == \"iphone\" || OS.device == \"ipod\") && OS.majorVersion < 7,\n SUPPORT_SWIPE_TO_GO_BACK = (OS.device == \"iphone\" || OS.device == \"ipod\") && OS.majorVersion >= 7,\n HISTORY_TRANSITION = SUPPORT_SWIPE_TO_GO_BACK ? \"none\" : null,\n BARCOMPENSATION = OS.browser == \"mobilesafari\" ? 60 : 0,\n STATUS_BAR_HEIGHT = 20,\n WINDOW = $(window),\n SCREEN = window.screen,\n HEAD = $(\"head\"),\n\n // mobile app events\n INIT = \"init\",\n proxy = $.proxy;\n\n function osCssClass(os, options) {\n var classes = [];\n\n if (OS) {\n classes.push(\"km-on-\" + OS.name);\n }\n\n if (os.skin) {\n classes.push(\"km-\" + os.skin);\n } else {\n if (os.name == \"ios\" && os.majorVersion > 6) {\n classes.push(\"km-ios7\");\n } else {\n classes.push(\"km-\" + os.name);\n }\n }\n if ((os.name == \"ios\" && os.majorVersion < 7) || os.name != \"ios\") {\n classes.push(\"km-\" + os.name + os.majorVersion);\n }\n classes.push(\"km-\" + os.majorVersion);\n classes.push(\"km-m\" + (os.minorVersion ? os.minorVersion[0] : 0));\n\n if (os.variant && ((os.skin && os.skin === os.name) || !os.skin)) {\n classes.push(\"km-\" + (os.skin ? os.skin : os.name) + \"-\" + os.variant);\n }\n\n if (os.cordova) {\n classes.push(\"km-cordova\");\n }\n if (os.appMode) {\n classes.push(\"km-app\");\n } else {\n classes.push(\"km-web\");\n }\n\n if (options && options.statusBarStyle) {\n classes.push(\"km-\" + options.statusBarStyle + \"-status-bar\");\n }\n\n return classes.join(\" \");\n }\n\n function wp8Background() {\n return parseInt($(\"
    \").css(\"background-color\").split(\",\")[1], 10) === 0 ? 'dark' : 'light';\n }\n\n function isOrientationHorizontal(element) {\n return OS.wp ? element.css(\"animation-name\") == \"-kendo-landscape\" : (Math.abs(window.orientation) / 90 == 1);\n }\n\n function getOrientationClass(element) {\n return isOrientationHorizontal(element) ? HORIZONTAL : VERTICAL;\n }\n\n function setMinimumHeight(pane) {\n pane.parent().addBack()\n .css(\"min-height\", window.innerHeight);\n }\n\n function applyViewportHeight() {\n $(\"meta[name=viewport]\").remove();\n HEAD.append(viewportTemplate({\n height: \", width=device-width\" + // width=device-width was removed for iOS6, but this should stay for BB PhoneGap.\n (isOrientationHorizontal() ?\n \", height=\" + window.innerHeight + \"px\" :\n (support.mobileOS.flatVersion >= 600 && support.mobileOS.flatVersion < 700) ?\n \", height=\" + window.innerWidth + \"px\" :\n \", height=device-height\")\n }));\n }\n\n var Application = kendo.Observable.extend({\n init: function(element, options) {\n var that = this;\n\n mobile.application = that; // global reference to current application\n\n that.options = $.extend({\n hideAddressBar: true,\n useNativeScrolling: false,\n statusBarStyle: \"black\",\n transition: \"\",\n historyTransition: HISTORY_TRANSITION,\n modelScope: window,\n updateDocumentTitle: true\n }, options);\n\n kendo.Observable.fn.init.call(that, that.options);\n that.bind(that.events, that.options);\n\n $(function(){\n element = $(element);\n that.element = element[0] ? element : $(document.body);\n that._setupPlatform();\n that._attachMeta();\n that._setupElementClass();\n that._attachHideBarHandlers();\n that.pane = new Pane(that.element, that.options);\n that.pane.navigateToInitial();\n\n if (that.options.updateDocumentTitle) {\n that._setupDocumentTitle();\n }\n\n that._startHistory();\n that.trigger(INIT);\n });\n },\n\n events: [\n INIT\n ],\n\n navigate: function(url, transition) {\n this.pane.navigate(url, transition);\n },\n\n replace: function(url, transition) {\n this.pane.replace(url, transition);\n },\n\n scroller: function() {\n return this.view().scroller;\n },\n\n hideLoading: function() {\n if (this.pane) {\n this.pane.hideLoading();\n } else {\n throw new Error(\"The mobile application instance is not fully instantiated. Please consider activating loading in the application init event handler.\");\n }\n },\n\n showLoading: function() {\n if (this.pane) {\n this.pane.showLoading();\n } else {\n throw new Error(\"The mobile application instance is not fully instantiated. Please consider activating loading in the application init event handler.\");\n }\n },\n\n changeLoadingMessage: function(message) {\n if (this.pane) {\n this.pane.changeLoadingMessage(message);\n } else {\n throw new Error(\"The mobile application instance is not fully instantiated. Please consider changing the message in the application init event handler.\");\n }\n },\n\n view: function() {\n return this.pane.view();\n },\n\n skin: function(skin) {\n var that = this;\n\n if (!arguments.length) {\n return that.options.skin;\n }\n\n that.options.skin = skin || \"\";\n that.element[0].className = \"km-pane\";\n that._setupPlatform();\n that._setupElementClass();\n\n return that.options.skin;\n },\n\n destroy: function() {\n this.pane.destroy();\n this.router.destroy();\n },\n\n _setupPlatform: function() {\n var that = this,\n platform = that.options.platform,\n skin = that.options.skin,\n split = [],\n os = OS || MOBILE_PLATFORMS[DEFAULT_OS];\n\n if (platform) {\n if (typeof platform === \"string\") {\n split = platform.split(\"-\");\n os = $.extend({ variant: split[1] }, os, MOBILE_PLATFORMS[split[0]]);\n } else {\n os = platform;\n }\n }\n\n if (skin) {\n split = skin.split(\"-\");\n os = $.extend({}, os, { skin: split[0], variant: split[1] });\n }\n\n if (!os.variant) {\n os.variant = \"dark\";\n }\n\n that.os = os;\n\n that.osCssClass = osCssClass(that.os, that.options);\n\n if (os.wp) {\n if (!that.refreshBackgroundColorProxy) {\n that.refreshBackgroundColorProxy = $.proxy(function () {\n if ((that.os.variant && ((that.os.skin && that.os.skin === that.os.name)) || !that.os.skin)) {\n that.element.removeClass(\"km-wp-dark km-wp-light\").addClass(\"km-wp-\" + wp8Background());\n }\n }, that);\n }\n\n $(window).off(\"focusin\", that.refreshBackgroundColorProxy);\n $(document).off(\"resume\", that.refreshBackgroundColorProxy);\n\n if (!os.skin) {\n that.element.parent().css(\"overflow\", \"hidden\");\n\n $(window).on(\"focusin\", that.refreshBackgroundColorProxy); // Restore theme on browser focus (requires click).\n $(document).on(\"resume\", that.refreshBackgroundColorProxy); // PhoneGap fires resume.\n\n that.refreshBackgroundColorProxy();\n }\n }\n },\n\n _startHistory: function() {\n this.router = new kendo.Router({ pushState: this.options.pushState, root: this.options.root, hashBang: this.options.hashBang });\n this.pane.bindToRouter(this.router);\n this.router.start();\n },\n\n _resizeToScreenHeight: function() {\n var includeStatusBar = $(\"meta[name=apple-mobile-web-app-status-bar-style]\").attr(\"content\").match(/black-translucent|hidden/),\n element = this.element,\n height;\n\n if (CHROME) {\n height = window.innerHeight;\n } else {\n if (isOrientationHorizontal(element)) {\n if (includeStatusBar) {\n if (INITIALLY_HORIZONTAL) {\n height = SCREEN.availWidth + STATUS_BAR_HEIGHT;\n } else {\n height = SCREEN.availWidth;\n }\n } else {\n if (INITIALLY_HORIZONTAL) {\n height = SCREEN.availWidth;\n } else {\n height = SCREEN.availWidth - STATUS_BAR_HEIGHT;\n }\n }\n } else {\n if (includeStatusBar) {\n if (INITIALLY_HORIZONTAL) {\n height = SCREEN.availHeight;\n } else {\n height = SCREEN.availHeight + STATUS_BAR_HEIGHT;\n }\n } else {\n if (INITIALLY_HORIZONTAL) {\n height = SCREEN.availHeight - STATUS_BAR_HEIGHT;\n } else {\n height = SCREEN.availHeight;\n }\n }\n }\n }\n\n element.height(height);\n },\n\n _setupElementClass: function() {\n var that = this, size,\n element = that.element;\n\n element.parent().addClass(\"km-root km-\" + (that.os.tablet ? \"tablet\" : \"phone\"));\n element.addClass(that.osCssClass + \" \" + getOrientationClass(element));\n if (this.options.useNativeScrolling) {\n element.parent().addClass(\"km-native-scrolling\");\n }\n\n if (CHROME) {\n element.addClass(\"km-ios-chrome\");\n }\n\n if (support.wpDevicePixelRatio) {\n element.parent().css(\"font-size\", support.wpDevicePixelRatio + \"em\");\n }\n\n if (BERRYPHONEGAP) {\n applyViewportHeight();\n }\n if (that.options.useNativeScrolling) {\n element.parent().addClass(\"km-native-scrolling\");\n } else if (ENABLE_CLIP) {\n size = (screen.availWidth > screen.availHeight ? screen.availWidth : screen.availHeight) + 200;\n $(clipTemplate({ width: size, height: size })).appendTo(HEAD);\n }\n\n if (BROKEN_WEBVIEW_RESIZE) {\n that._resizeToScreenHeight();\n }\n\n kendo.onResize(function() {\n element\n .removeClass(\"km-horizontal km-vertical\")\n .addClass(getOrientationClass(element));\n\n if (that.options.useNativeScrolling) {\n setMinimumHeight(element);\n }\n\n if (BROKEN_WEBVIEW_RESIZE) {\n that._resizeToScreenHeight();\n }\n\n if (BERRYPHONEGAP) {\n applyViewportHeight();\n }\n\n kendo.resize(element);\n });\n },\n\n _clearExistingMeta: function() {\n HEAD.find(\"meta\")\n .filter(\"[name|='apple-mobile-web-app'],[name|='msapplication-tap'],[name='viewport']\")\n .remove();\n },\n\n _attachMeta: function() {\n var options = this.options,\n icon = options.icon, size;\n\n this._clearExistingMeta();\n\n if (!BERRYPHONEGAP) {\n HEAD.prepend(viewportMeta);\n }\n\n HEAD.prepend(systemMeta(options));\n\n if (icon) {\n if (typeof icon === \"string\") {\n icon = { \"\" : icon };\n }\n\n for(size in icon) {\n HEAD.prepend(iconMeta({ icon: icon[size], size: size }));\n }\n }\n\n if (options.useNativeScrolling) {\n setMinimumHeight(this.element);\n }\n },\n\n _attachHideBarHandlers: function() {\n var that = this,\n hideBar = proxy(that, \"_hideBar\");\n\n if (support.mobileOS.appMode || !that.options.hideAddressBar || !HIDEBAR || that.options.useNativeScrolling) {\n return;\n }\n\n that._initialHeight = {};\n\n WINDOW.on(\"load\", hideBar);\n\n kendo.onResize(function() {\n setTimeout(window.scrollTo, 0, 0, 1);\n });\n },\n\n _setupDocumentTitle: function() {\n var that = this,\n defaultTitle = document.title;\n\n that.pane.bind(\"viewShow\", function(e) {\n var title = e.view.title;\n document.title = title !== undefined ? title : defaultTitle;\n });\n },\n\n _hideBar: function() {\n var that = this,\n element = that.element;\n\n element.height(kendo.support.transforms.css + \"calc(100% + \" + BARCOMPENSATION + \"px)\");\n $(window).trigger(kendo.support.resize);\n }\n });\n\n kendo.mobile.Application = Application;\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.userevents\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n mobile = kendo.mobile,\n ui = mobile.ui,\n Widget = ui.Widget,\n support = kendo.support,\n os = support.mobileOS,\n ANDROID3UP = os.android && os.flatVersion >= 300,\n CLICK = \"click\",\n DISABLED = \"disabled\",\n DISABLEDSTATE = \"km-state-disabled\";\n\n function highlightButton(widget, event, highlight) {\n $(event.target).closest(\".km-button,.km-detail\").toggleClass(\"km-state-active\", highlight);\n\n if (ANDROID3UP && widget.deactivateTimeoutID) {\n clearTimeout(widget.deactivateTimeoutID);\n widget.deactivateTimeoutID = 0;\n }\n }\n\n function createBadge(value) {\n return $('' + value + '');\n }\n\n var Button = Widget.extend({\n init: function(element, options) {\n var that = this;\n\n Widget.fn.init.call(that, element, options);\n\n that._wrap();\n that._style();\n\n that.options.enable = that.options.enable && !that.element.attr(DISABLED);\n that.enable(that.options.enable);\n\n that._userEvents = new kendo.UserEvents(that.element, {\n press: function(e) { that._activate(e); },\n tap: function(e) { that._release(e); },\n release: function(e) { highlightButton(that, e, false); }\n });\n\n if (ANDROID3UP) {\n that.element.on(\"move\", function(e) { that._timeoutDeactivate(e); });\n }\n },\n\n destroy: function() {\n Widget.fn.destroy.call(this);\n this._userEvents.destroy();\n },\n\n events: [\n CLICK\n ],\n\n options: {\n name: \"Button\",\n icon: \"\",\n style: \"\",\n badge: \"\",\n enable: true\n },\n\n badge: function (value) {\n var badge = this.badgeElement = this.badgeElement || createBadge(value).appendTo(this.element);\n\n if (value || value === 0) {\n badge.html(value);\n return this;\n }\n\n if (value === false) {\n badge.empty().remove();\n this.badgeElement = false;\n return this;\n }\n\n return badge.html();\n },\n\n enable: function(enable) {\n var element = this.element;\n\n if(typeof enable == \"undefined\") {\n enable = true;\n }\n\n this.options.enable = enable;\n\n if(enable) {\n element.removeAttr(DISABLED);\n } else {\n element.attr(DISABLED, DISABLED);\n }\n\n element.toggleClass(DISABLEDSTATE, !enable);\n },\n\n _timeoutDeactivate: function(e) {\n if (!this.deactivateTimeoutID) {\n this.deactivateTimeoutID = setTimeout(highlightButton, 500, this, e, false);\n }\n },\n\n _activate: function(e) {\n var activeElement = document.activeElement,\n nodeName = activeElement ? activeElement.nodeName : \"\";\n\n if(this.options.enable) {\n highlightButton(this, e, true);\n\n if (nodeName == \"INPUT\" || nodeName == \"TEXTAREA\") {\n activeElement.blur(); // Hide device keyboard\n }\n }\n },\n\n _release: function(e) {\n var that = this;\n\n if (e.which > 1) {\n return;\n }\n\n if(!that.options.enable) {\n e.preventDefault();\n return;\n }\n\n if (that.trigger(CLICK, {target: $(e.target), button: that.element})) {\n e.preventDefault();\n }\n },\n\n _style: function() {\n var style = this.options.style,\n element = this.element,\n styles;\n\n if (style) {\n styles = style.split(\" \");\n $.each(styles, function() {\n element.addClass(\"km-\" + this);\n });\n }\n },\n\n _wrap: function() {\n var that = this,\n icon = that.options.icon,\n badge = that.options.badge,\n iconSpan = '').children(\"span.km-text\");\n }\n\n if (!image[0] && icon) {\n if (!span[0]) {\n iconSpan += \" km-notext\";\n }\n that.iconElement = element.prepend($(iconSpan + '\" />'));\n }\n\n if (badge || badge === 0) {\n that.badgeElement = createBadge(badge).appendTo(element);\n }\n }\n });\n\n var BackButton = Button.extend({\n options: {\n name: \"BackButton\",\n style: \"back\"\n },\n\n init: function(element, options) {\n var that = this;\n Button.fn.init.call(that, element, options);\n\n if (typeof that.element.attr(\"href\") === \"undefined\") {\n that.element.attr(\"href\", \"#:back\");\n }\n }\n });\n\n var DetailButton = Button.extend({\n options: {\n name: \"DetailButton\",\n style: \"\"\n },\n\n init: function(element, options) {\n Button.fn.init.call(this, element, options);\n },\n\n _style: function() {\n var style = this.options.style + \" detail\",\n element = this.element;\n\n if (style) {\n var styles = style.split(\" \");\n $.each(styles, function() {\n element.addClass(\"km-\" + this);\n });\n }\n },\n\n _wrap: function() {\n var that = this,\n icon = that.options.icon,\n iconSpan = ''));\n }\n }\n\n });\n\n ui.plugin(Button);\n ui.plugin(BackButton);\n ui.plugin(DetailButton);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n/*\n* Kendo UI v2014.2.716 (http://www.telerik.com/kendo-ui)\n* Copyright 2014 Telerik AD. All rights reserved.\n*\n* Kendo UI commercial licenses may be obtained at\n* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete\n* If you do not own a commercial license, this file shall be governed by the trial license terms.\n*/\n(function(f, define){\n define([ \"./kendo.core\", \"./kendo.userevents\" ], f);\n})(function(){\n\n(function($, undefined) {\n var kendo = window.kendo,\n Widget = kendo.ui.Widget,\n proxy = $.proxy,\n abs = Math.abs,\n MAX_DOUBLE_TAP_DISTANCE = 20;\n\n var Swipe = kendo.Class.extend({\n init: function(element, callback, options) {\n options = $.extend({\n minXDelta: 30,\n maxYDelta: 20,\n maxDuration: 1000\n }, options);\n\n new kendo.UserEvents(element, {\n surface: options.surface,\n allowSelection: true,\n\n start: function(e) {\n if (abs(e.x.velocity) * 2 >= abs(e.y.velocity)) {\n e.sender.capture();\n }\n },\n\n move: function(e) {\n var touch = e.touch,\n duration = e.event.timeStamp - touch.startTime,\n direction = touch.x.initialDelta > 0 ? \"right\" : \"left\";\n\n if (\n abs(touch.x.initialDelta) >= options.minXDelta &&\n abs(touch.y.initialDelta) < options.maxYDelta &&\n duration < options.maxDuration)\n {\n callback({\n direction: direction,\n touch: touch,\n target: touch.target\n });\n\n touch.cancel();\n }\n }\n });\n }\n });\n\n var Touch = Widget.extend({\n init: function(element, options) {\n var that = this;\n\n Widget.fn.init.call(that, element, options);\n options = that.options;\n\n element = that.element;\n\n function eventProxy(name) {\n return function(e) {\n that._triggerTouch(name, e);\n };\n }\n\n function gestureEventProxy(name) {\n return function(e) {\n that.trigger(name, { touches: e.touches, distance: e.distance, center: e.center, event: e.event });\n };\n }\n\n that.events = new kendo.UserEvents(element, {\n filter: options.filter,\n surface: options.surface,\n minHold: options.minHold,\n multiTouch: options.multiTouch,\n allowSelection: true,\n press: eventProxy(\"touchstart\"),\n hold: eventProxy(\"hold\"),\n tap: proxy(that, \"_tap\"),\n gesturestart: gestureEventProxy(\"gesturestart\"),\n gesturechange: gestureEventProxy(\"gesturechange\"),\n gestureend: gestureEventProxy(\"gestureend\")\n });\n\n if (options.enableSwipe) {\n that.events.bind(\"start\", proxy(that, \"_swipestart\"));\n that.events.bind(\"move\", proxy(that, \"_swipemove\"));\n } else {\n that.events.bind(\"start\", proxy(that, \"_dragstart\"));\n that.events.bind(\"move\", eventProxy(\"drag\"));\n that.events.bind(\"end\", eventProxy(\"dragend\"));\n }\n\n kendo.notify(that);\n },\n\n events: [\n \"touchstart\",\n \"dragstart\",\n \"drag\",\n \"dragend\",\n \"tap\",\n \"doubletap\",\n \"hold\",\n \"swipe\",\n \"gesturestart\",\n \"gesturechange\",\n \"gestureend\"\n ],\n\n options: {\n name: \"Touch\",\n surface: null,\n global: false,\n multiTouch: false,\n enableSwipe: false,\n minXDelta: 30,\n maxYDelta: 20,\n maxDuration: 1000,\n minHold: 800,\n doubleTapTimeout: 800\n },\n\n cancel: function() {\n this.events.cancel();\n },\n\n _triggerTouch: function(type, e) {\n if (this.trigger(type, { touch: e.touch, event: e.event })) {\n e.preventDefault();\n }\n },\n\n _tap: function(e) {\n var that = this,\n lastTap = that.lastTap,\n touch = e.touch;\n\n if (lastTap &&\n (touch.endTime - lastTap.endTime < that.options.doubleTapTimeout) &&\n kendo.touchDelta(touch, lastTap).distance < MAX_DOUBLE_TAP_DISTANCE\n ) {\n\n that._triggerTouch(\"doubletap\", e);\n that.lastTap = null;\n } else {\n that._triggerTouch(\"tap\", e);\n that.lastTap = touch;\n }\n },\n\n _dragstart: function(e) {\n this._triggerTouch(\"dragstart\", e);\n },\n\n _swipestart: function(e) {\n if (abs(e.x.velocity) * 2 >= abs(e.y.velocity)) {\n e.sender.capture();\n }\n },\n\n _swipemove: function(e) {\n var that = this,\n options = that.options,\n touch = e.touch,\n duration = e.event.timeStamp - touch.startTime,\n direction = touch.x.initialDelta > 0 ? \"right\" : \"left\";\n\n if (\n abs(touch.x.initialDelta) >= options.minXDelta &&\n abs(touch.y.initialDelta) < options.maxYDelta &&\n duration < options.maxDuration\n )\n {\n that.trigger(\"swipe\", {\n direction: direction,\n touch: e.touch\n });\n\n touch.cancel();\n }\n }\n });\n\n\n window.jQuery.fn.kendoMobileSwipe = function(callback, options) {\n this.each(function() {\n new Swipe(this, callback, options);\n });\n };\n\n kendo.ui.plugin(Touch);\n})(window.kendo.jQuery);\n\nreturn window.kendo;\n\n}, typeof define == 'function' && define.amd ? define : function(_, f){ f(); });\n// Knockout JavaScript library v3.0.0\n// (c) Steven Sanderson - http://knockoutjs.com/\n// License: MIT (http://www.opensource.org/licenses/mit-license.php)\n\n(function() {(function(q){var y=this||(0,eval)(\"this\"),w=y.document,K=y.navigator,u=y.jQuery,B=y.JSON;(function(q){\"function\"===typeof require&&\"object\"===typeof exports&&\"object\"===typeof module?q(module.exports||exports):\"function\"===typeof define&&define.amd?define([\"exports\"],q):q(y.ko={})})(function(F){function G(a,c){return null===a||typeof a in N?a===c:!1}function H(b,c,d,e){a.d[b]={init:function(b){a.a.f.set(b,L,{});return{controlsDescendantBindings:!0}},update:function(b,h,k,m,f){k=a.a.f.get(b,L);h=a.a.c(h());\nm=!d!==!h;var p=!k.ob;if(p||c||m!==k.Db)p&&(k.ob=a.a.Ya(a.e.childNodes(b),!0)),m?(p||a.e.S(b,a.a.Ya(k.ob)),a.Ta(e?e(f,h):f,b)):a.e.Z(b),k.Db=m}};a.g.Y[b]=!1;a.e.P[b]=!0}var a=\"undefined\"!==typeof F?F:{};a.b=function(b,c){for(var d=b.split(\".\"),e=a,g=0;ga.a.l(c,b[f])&&c.push(b[f]);return c},ha:function(a,b){a=a||[];for(var f=[],c=0,d=a.length;cd?f&&b.push(c):f||b.splice(d,1)},extend:function(a,b){if(b)for(var f in b)b.hasOwnProperty(f)&&\n(a[f]=b[f]);return a},K:b,Da:function(a,b){if(!a)return a;var f={},c;for(c in a)a.hasOwnProperty(c)&&(f[c]=b(a[c],c,a));return f},wa:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Vb:function(b){b=a.a.Q(b);for(var c=w.createElement(\"div\"),f=0,d=b.length;fh?a.setAttribute(\"selected\",b):a.selected=b},la:function(a){return null===a||a===\nq?\"\":a.trim?a.trim():a.toString().replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\")},ec:function(b,c){for(var f=[],d=(b||\"\").split(c),e=0,g=d.length;ea.length?!1:a.substring(0,b.length)===b},Gb:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;\nreturn!!a},va:function(b){return a.a.Gb(b,b.ownerDocument.documentElement)},Ra:function(b){return!!a.a.Ua(b,a.a.va)},v:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},r:function(b,d,f){var e=h&&g[d];if(e||\"undefined\"==typeof u)if(e||\"function\"!=typeof b.addEventListener)if(\"undefined\"!=typeof b.attachEvent){var s=function(a){f.call(b,a)},l=\"on\"+d;b.attachEvent(l,s);a.a.C.ea(b,function(){b.detachEvent(l,s)})}else throw Error(\"Browser doesn't support addEventListener or attachEvent\");else b.addEventListener(d,\nf,!1);else{if(c(b,d)){var n=f;f=function(a,b){var f=this.checked;b&&(this.checked=!0!==b.Ab);n.call(this,a);this.checked=f}}u(b).bind(d,f)}},da:function(a,b){if(!a||!a.nodeType)throw Error(\"element must be a DOM node when calling triggerEvent\");if(\"undefined\"!=typeof u){var f=[];c(a,b)&&f.push({Ab:a.checked});u(a).trigger(b,f)}else if(\"function\"==typeof w.createEvent)if(\"function\"==typeof a.dispatchEvent)f=w.createEvent(e[b]||\"HTMLEvents\"),f.initEvent(b,!0,!0,y,0,0,0,0,0,!1,!1,!1,!1,0,a),a.dispatchEvent(f);\nelse throw Error(\"The supplied element doesn't support dispatchEvent\");else if(\"undefined\"!=typeof a.fireEvent)c(a,b)&&(a.checked=!0!==a.checked),a.fireEvent(\"on\"+b);else throw Error(\"Browser doesn't support triggering events\");},c:function(b){return a.M(b)?b():b},Ha:function(b){return a.M(b)?b.t():b},ma:function(b,c,f){if(c){var d=/\\S+/g,e=b.className.match(d)||[];a.a.n(c.match(d),function(b){a.a.V(e,b,f)});b.className=e.join(\" \")}},Ma:function(b,c){var f=a.a.c(c);if(null===f||f===q)f=\"\";var d=a.e.firstChild(b);\n!d||3!=d.nodeType||a.e.nextSibling(d)?a.e.S(b,[w.createTextNode(f)]):d.data=f;a.a.Jb(b)},pb:function(a,b){a.name=b;if(7>=h)try{a.mergeAttributes(w.createElement(\"\"),!1)}catch(f){}},Jb:function(a){9<=h&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},Hb:function(a){if(h){var b=a.style.width;a.style.width=0;a.style.width=b}},Zb:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var f=[],d=b;d<=c;d++)f.push(d);return f},Q:function(a){for(var b=[],c=0,d=a.length;c<\nd;c++)b.push(a[c]);return b},cc:6===h,dc:7===h,ja:h,ab:function(b,c){for(var f=a.a.Q(b.getElementsByTagName(\"input\")).concat(a.a.Q(b.getElementsByTagName(\"textarea\"))),d=\"string\"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},e=[],g=f.length-1;0<=g;g--)d(f[g])&&e.push(f[g]);return e},Wb:function(b){return\"string\"==typeof b&&(b=a.a.la(b))?B&&B.parse?B.parse(b):(new Function(\"return \"+b))():null},Na:function(b,c,f){if(!B||!B.stringify)throw Error(\"Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js\");\nreturn B.stringify(a.a.c(b),c,f)},Xb:function(c,d,f){f=f||{};var e=f.params||{},g=f.includeFields||this.$a,h=c;if(\"object\"==typeof c&&\"form\"===a.a.v(c))for(var h=c.action,n=g.length-1;0<=n;n--)for(var r=a.a.ab(c,g[n]),v=r.length-1;0<=v;v--)e[r[v].name]=r[v].value;d=a.a.c(d);var t=w.createElement(\"form\");t.style.display=\"none\";t.action=h;t.method=\"post\";for(var E in d)c=w.createElement(\"input\"),c.name=E,c.value=a.a.Na(a.a.c(d[E])),t.appendChild(c);b(e,function(a,b){var c=w.createElement(\"input\");c.name=\na;c.value=b;t.appendChild(c)});w.body.appendChild(t);f.submitter?f.submitter(t):t.submit();setTimeout(function(){t.parentNode.removeChild(t)},0)}}}();a.b(\"utils\",a.a);a.b(\"utils.arrayForEach\",a.a.n);a.b(\"utils.arrayFirst\",a.a.Ua);a.b(\"utils.arrayFilter\",a.a.ga);a.b(\"utils.arrayGetDistinctValues\",a.a.Va);a.b(\"utils.arrayIndexOf\",a.a.l);a.b(\"utils.arrayMap\",a.a.ha);a.b(\"utils.arrayPushAll\",a.a.X);a.b(\"utils.arrayRemoveItem\",a.a.ia);a.b(\"utils.extend\",a.a.extend);a.b(\"utils.fieldsIncludedWithJsonPost\",\na.a.$a);a.b(\"utils.getFormFields\",a.a.ab);a.b(\"utils.peekObservable\",a.a.Ha);a.b(\"utils.postJson\",a.a.Xb);a.b(\"utils.parseJson\",a.a.Wb);a.b(\"utils.registerEventHandler\",a.a.r);a.b(\"utils.stringifyJson\",a.a.Na);a.b(\"utils.range\",a.a.Zb);a.b(\"utils.toggleDomNodeCssClass\",a.a.ma);a.b(\"utils.triggerEvent\",a.a.da);a.b(\"utils.unwrapObservable\",a.a.c);a.b(\"utils.objectForEach\",a.a.K);a.b(\"utils.addOrRemoveItem\",a.a.V);a.b(\"unwrap\",a.a.c);Function.prototype.bind||(Function.prototype.bind=function(a){var c=\nthis,d=Array.prototype.slice.call(arguments);a=d.shift();return function(){return c.apply(a,d.concat(Array.prototype.slice.call(arguments)))}});a.a.f=new function(){function a(b,h){var k=b[d];if(!k||\"null\"===k||!e[k]){if(!h)return q;k=b[d]=\"ko\"+c++;e[k]={}}return e[k]}var c=0,d=\"__ko__\"+(new Date).getTime(),e={};return{get:function(c,d){var e=a(c,!1);return e===q?q:e[d]},set:function(c,d,e){if(e!==q||a(c,!1)!==q)a(c,!0)[d]=e},clear:function(a){var b=a[d];return b?(delete e[b],a[d]=null,!0):!1},D:function(){return c++ +\nd}}};a.b(\"utils.domData\",a.a.f);a.b(\"utils.domData.clear\",a.a.f.clear);a.a.C=new function(){function b(b,c){var e=a.a.f.get(b,d);e===q&&c&&(e=[],a.a.f.set(b,d,e));return e}function c(d){var e=b(d,!1);if(e)for(var e=e.slice(0),m=0;m\",\"\"]||!d.indexOf(\"\",\"\"]||(!d.indexOf(\"\",\"\"]||[0,\"\",\"\"];b=\"ignored
    \"+d[1]+b+d[2]+\"
    \";for(\"function\"==typeof y.innerShiv?c.appendChild(y.innerShiv(b)):c.innerHTML=b;d[0]--;)c=c.lastChild;c=a.a.Q(c.lastChild.childNodes)}return c};a.a.Ka=function(b,c){a.a.wa(b);c=a.a.c(c);if(null!==c&&c!==q)if(\"string\"!=typeof c&&(c=c.toString()),\"undefined\"!=typeof u)u(b).html(c);else for(var d=a.a.Fa(c),e=0;ec[0]?l+c[0]:c[0]),l);for(var l=1===n?l:Math.min(b+(c[1]||0),l),n=b+n-2,r=Math.max(l,n),v=2;bc;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.tb(b);return a.a.Na(b,c,d)};d.prototype={save:function(b,c){var d=a.a.l(this.keys,b);0<=d?this.Qa[d]=c:(this.keys.push(b),this.Qa.push(c))},get:function(b){b=a.a.l(this.keys,b);return 0<=b?this.Qa[b]:q}}})();a.b(\"toJS\",a.tb);a.b(\"toJSON\",a.toJSON);(function(){a.k={o:function(b){switch(a.a.v(b)){case \"option\":return!0===\nb.__ko__hasDomDataOptionValue__?a.a.f.get(b,a.d.options.Ea):7>=a.a.ja?b.getAttributeNode(\"value\")&&b.getAttributeNode(\"value\").specified?b.value:b.text:b.value;case \"select\":return 0<=b.selectedIndex?a.k.o(b.options[b.selectedIndex]):q;default:return b.value}},na:function(b,c){switch(a.a.v(b)){case \"option\":switch(typeof c){case \"string\":a.a.f.set(b,a.d.options.Ea,q);\"__ko__hasDomDataOptionValue__\"in b&&delete b.__ko__hasDomDataOptionValue__;b.value=c;break;default:a.a.f.set(b,a.d.options.Ea,c),b.__ko__hasDomDataOptionValue__=\n!0,b.value=\"number\"===typeof c?c:\"\"}break;case \"select\":\"\"===c&&(c=q);if(null===c||c===q)b.selectedIndex=-1;for(var d=b.options.length-1;0<=d;d--)if(a.k.o(b.options[d])==c){b.selectedIndex=d;break}1=n){k&&c.push(l?{key:k,value:l.join(\"\")}:{unknown:k});k=l=n=0;continue}}else if(58===t){if(!l)continue}else if(47===t&&r&&1=a.a.ja&&c in M?(c=M[c],h?b.removeAttribute(c):b[c]=d):h||b.setAttribute(c,\nd.toString());\"name\"===c&&a.a.pb(b,h?\"\":d.toString())})}};(function(){a.d.checked={after:[\"value\",\"attr\"],init:function(b,c,d){function e(){return d.has(\"checkedValue\")?a.a.c(d.get(\"checkedValue\")):b.value}function g(){var k=b.checked,g=s?e():k;if(l&&(!m||k)){var h=a.i.p(c);f?p!==g?(k&&(a.a.V(h,g,!0),a.a.V(h,p,!1)),p=g):a.a.V(h,g,k):a.g.oa(h,d,\"checked\",g,!0)}}function h(){var d=a.a.c(c());b.checked=f?0<=a.a.l(d,e()):k?d:e()===d}var k=\"checkbox\"==b.type,m=\"radio\"==b.type;if(k||m){var f=k&&a.a.c(c())instanceof\nArray,p=f?e():q,s=m||f,l=!1;m&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.h(g,null,{I:b});a.a.r(b,\"click\",g);a.h(h,null,{I:b});l=!0}}};a.g.U.checked=!0;a.d.checkedValue={update:function(b,c){b.value=a.a.c(c())}}})();a.d.css={update:function(b,c){var d=a.a.c(c());\"object\"==typeof d?a.a.K(d,function(c,d){d=a.a.c(d);a.a.ma(b,c,d)}):(d=String(d||\"\"),a.a.ma(b,b.__ko__cssValue,!1),b.__ko__cssValue=d,a.a.ma(b,d,!0))}};a.d.enable={update:function(b,c){var d=a.a.c(c());d&&b.disabled?b.removeAttribute(\"disabled\"):\nd||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,c){a.d.enable.update(b,function(){return!a.a.c(c())})}};a.d.event={init:function(b,c,d,e,g){var h=c()||{};a.a.K(h,function(k){\"string\"==typeof k&&a.a.r(b,k,function(b){var f,h=c()[k];if(h){try{var s=a.a.Q(arguments);e=g.$data;s.unshift(e);f=h.apply(e,s)}finally{!0!==f&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(k+\"Bubble\")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={hb:function(b){return function(){var c=\nb(),d=a.a.Ha(c);if(!d||\"number\"==typeof d.length)return{foreach:c,templateEngine:a.J.Aa};a.a.c(c);return{foreach:d.data,as:d.as,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.J.Aa}}},init:function(b,c){return a.d.template.init(b,a.d.foreach.hb(c))},update:function(b,c,d,e,g){return a.d.template.update(b,a.d.foreach.hb(c),d,e,g)}};a.g.Y.foreach=!1;a.e.P.foreach=!0;a.d.hasfocus=\n{init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var g=b.ownerDocument;if(\"activeElement\"in g){var f;try{f=g.activeElement}catch(h){f=g.body}e=f===b}g=c();a.g.oa(g,d,\"hasfocus\",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var g=e.bind(null,!0),h=e.bind(null,!1);a.a.r(b,\"focus\",g);a.a.r(b,\"focusin\",g);a.a.r(b,\"blur\",h);a.a.r(b,\"focusout\",h)},update:function(b,c){var d=!!a.a.c(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===d||(d?b.focus():b.blur(),a.i.p(a.a.da,\nnull,[b,d?\"focusin\":\"focusout\"]))}};a.g.U.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.g.U.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Ka(b,c())}};var L=a.a.f.D();H(\"if\");H(\"ifnot\",!1,!0);H(\"with\",!0,!1,function(a,c){return a.createChildContext(c)});a.d.options={init:function(b){if(\"select\"!==a.a.v(b))throw Error(\"options binding applies only to SELECT elements\");for(;0a.a.ja?0:b.nodes)?b.nodes():null;if(c)return a.a.Q(c.cloneNode(!0).childNodes);b=b.text();return a.a.Fa(b)};a.J.Aa=\nnew a.J;a.La(a.J.Aa);a.b(\"nativeTemplateEngine\",a.J);(function(){a.Ba=function(){var a=this.Rb=function(){if(\"undefined\"==typeof u||!u.tmpl)return 0;try{if(0<=u.tmpl.tag.tmpl.open.toString().indexOf(\"__\"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,g){g=g||{};if(2>a)throw Error(\"Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.\");var h=b.data(\"precompiled\");h||(h=b.text()||\"\",h=u.template(null,\"{{ko_with $item.koBindingContext}}\"+h+\n\"{{/ko_with}}\"),b.data(\"precompiled\",h));b=[e.$data];e=u.extend({koBindingContext:e},g.templateOptions);e=u.tmpl(h,b,e);e.appendTo(w.createElement(\"div\"));u.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return\"{{ko_code ((function() { return \"+a+\" })()) }}\"};this.addTemplate=function(a,b){w.write(\"\r\n * \r\n * (end code)\r\n * \r\n * Please remember that when your OpenLayers script is not named \r\n * \"OpenLayers.js\" you will have to make sure that the default theme is \r\n * loaded into the page by including an appropriate -tag, \r\n * e.g.:\r\n * \r\n * (code)\r\n * \r\n * (end code)\r\n */\r\n ImgPath : ''\r\n};\r\n/* ======================================================================\r\n OpenLayers/BaseTypes/Class.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/SingleFile.js\r\n */\r\n\r\n/**\r\n * Constructor: OpenLayers.Class\r\n * Base class used to construct all other classes. Includes support for \r\n * multiple inheritance. \r\n * \r\n * This constructor is new in OpenLayers 2.5. At OpenLayers 3.0, the old \r\n * syntax for creating classes and dealing with inheritance \r\n * will be removed.\r\n * \r\n * To create a new OpenLayers-style class, use the following syntax:\r\n * (code)\r\n * var MyClass = OpenLayers.Class(prototype);\r\n * (end)\r\n *\r\n * To create a new OpenLayers-style class with multiple inheritance, use the\r\n * following syntax:\r\n * (code)\r\n * var MyClass = OpenLayers.Class(Class1, Class2, prototype);\r\n * (end)\r\n * \r\n * Note that instanceof reflection will only reveal Class1 as superclass.\r\n *\r\n */\r\nOpenLayers.Class = function() {\r\n var len = arguments.length;\r\n var P = arguments[0];\r\n var F = arguments[len-1];\r\n\r\n var C = typeof F.initialize == \"function\" ?\r\n F.initialize :\r\n function(){ P.prototype.initialize.apply(this, arguments); };\r\n\r\n if (len > 1) {\r\n var newArgs = [C, P].concat(\r\n Array.prototype.slice.call(arguments).slice(1, len-1), F);\r\n OpenLayers.inherit.apply(null, newArgs);\r\n } else {\r\n C.prototype = F;\r\n }\r\n return C;\r\n};\r\n\r\n/**\r\n * Function: OpenLayers.inherit\r\n *\r\n * Parameters:\r\n * C - {Object} the class that inherits\r\n * P - {Object} the superclass to inherit from\r\n *\r\n * In addition to the mandatory C and P parameters, an arbitrary number of\r\n * objects can be passed, which will extend C.\r\n */\r\nOpenLayers.inherit = function(C, P) {\r\n var F = function() {};\r\n F.prototype = P.prototype;\r\n C.prototype = new F;\r\n var i, l, o;\r\n for(i=2, l=arguments.length; i replacement = context[a];\r\n // 1 -> replacement = context[a][b];\r\n // 2 -> replacement = context[a][b][c];\r\n var subs = match.split(/\\.+/);\r\n for (var i=0; i< subs.length; i++) {\r\n if (i == 0) {\r\n replacement = context;\r\n }\r\n if (replacement === undefined) {\r\n break;\r\n }\r\n replacement = replacement[subs[i]];\r\n }\r\n\r\n if(typeof replacement == \"function\") {\r\n replacement = args ?\r\n replacement.apply(null, args) :\r\n replacement();\r\n }\r\n\r\n // If replacement is undefined, return the string 'undefined'.\r\n // This is a workaround for a bugs in browsers not properly \r\n // dealing with non-participating groups in regular expressions:\r\n // http://blog.stevenlevithan.com/archives/npcg-javascript\r\n if (typeof replacement == 'undefined') {\r\n return 'undefined';\r\n } else {\r\n return replacement; \r\n }\r\n };\r\n\r\n return template.replace(OpenLayers.String.tokenRegEx, replacer);\r\n },\r\n\r\n /**\r\n * Property: tokenRegEx\r\n * Used to find tokens in a string.\r\n * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}\r\n */\r\n tokenRegEx: /\\$\\{([\\w.]+?)\\}/g,\r\n \r\n /**\r\n * Property: numberRegEx\r\n * Used to test strings as numbers.\r\n */\r\n numberRegEx: /^([+-]?)(?=\\d|\\.\\d)\\d*(\\.\\d*)?([Ee]([+-]?\\d+))?$/,\r\n \r\n /**\r\n * APIFunction: isNumeric\r\n * Determine whether a string contains only a numeric value.\r\n *\r\n * Examples:\r\n * (code)\r\n * OpenLayers.String.isNumeric(\"6.02e23\") // true\r\n * OpenLayers.String.isNumeric(\"12 dozen\") // false\r\n * OpenLayers.String.isNumeric(\"4\") // true\r\n * OpenLayers.String.isNumeric(\" 4 \") // false\r\n * (end)\r\n *\r\n * Returns:\r\n * {Boolean} String contains only a number.\r\n */\r\n isNumeric: function(value) {\r\n return OpenLayers.String.numberRegEx.test(value);\r\n },\r\n \r\n /**\r\n * APIFunction: numericIf\r\n * Converts a string that appears to be a numeric value into a number.\r\n * \r\n * Parameters:\r\n * value - {String}\r\n * trimWhitespace - {Boolean}\r\n *\r\n * Returns:\r\n * {Number|String} a Number if the passed value is a number, a String\r\n * otherwise. \r\n */\r\n numericIf: function(value, trimWhitespace) {\r\n var originalValue = value;\r\n if (trimWhitespace === true && value != null && value.replace) {\r\n value = value.replace(/^\\s*|\\s*$/g, \"\");\r\n }\r\n return OpenLayers.String.isNumeric(value) ? parseFloat(value) : originalValue;\r\n }\r\n\r\n};\r\n\r\n/**\r\n * Namespace: OpenLayers.Number\r\n * Contains convenience functions for manipulating numbers.\r\n */\r\nOpenLayers.Number = {\r\n\r\n /**\r\n * Property: decimalSeparator\r\n * Decimal separator to use when formatting numbers.\r\n */\r\n decimalSeparator: \".\",\r\n \r\n /**\r\n * Property: thousandsSeparator\r\n * Thousands separator to use when formatting numbers.\r\n */\r\n thousandsSeparator: \",\",\r\n \r\n /**\r\n * APIFunction: limitSigDigs\r\n * Limit the number of significant digits on a float.\r\n * \r\n * Parameters:\r\n * num - {Float}\r\n * sig - {Integer}\r\n * \r\n * Returns:\r\n * {Float} The number, rounded to the specified number of significant\r\n * digits.\r\n */\r\n limitSigDigs: function(num, sig) {\r\n var fig = 0;\r\n if (sig > 0) {\r\n fig = parseFloat(num.toPrecision(sig));\r\n }\r\n return fig;\r\n },\r\n \r\n /**\r\n * APIFunction: format\r\n * Formats a number for output.\r\n * \r\n * Parameters:\r\n * num - {Float}\r\n * dec - {Integer} Number of decimal places to round to.\r\n * Defaults to 0. Set to null to leave decimal places unchanged.\r\n * tsep - {String} Thousands separator.\r\n * Default is \",\".\r\n * dsep - {String} Decimal separator.\r\n * Default is \".\".\r\n *\r\n * Returns:\r\n * {String} A string representing the formatted number.\r\n */\r\n format: function(num, dec, tsep, dsep) {\r\n dec = (typeof dec != \"undefined\") ? dec : 0; \r\n tsep = (typeof tsep != \"undefined\") ? tsep :\r\n OpenLayers.Number.thousandsSeparator; \r\n dsep = (typeof dsep != \"undefined\") ? dsep :\r\n OpenLayers.Number.decimalSeparator;\r\n\r\n if (dec != null) {\r\n num = parseFloat(num.toFixed(dec));\r\n }\r\n\r\n var parts = num.toString().split(\".\");\r\n if (parts.length == 1 && dec == null) {\r\n // integer where we do not want to touch the decimals\r\n dec = 0;\r\n }\r\n \r\n var integer = parts[0];\r\n if (tsep) {\r\n var thousands = /(-?[0-9]+)([0-9]{3})/; \r\n while(thousands.test(integer)) { \r\n integer = integer.replace(thousands, \"$1\" + tsep + \"$2\"); \r\n }\r\n }\r\n \r\n var str;\r\n if (dec == 0) {\r\n str = integer;\r\n } else {\r\n var rem = parts.length > 1 ? parts[1] : \"0\";\r\n if (dec != null) {\r\n rem = rem + new Array(dec - rem.length + 1).join(\"0\");\r\n }\r\n str = integer + dsep + rem;\r\n }\r\n return str;\r\n },\r\n\r\n /**\r\n * Method: zeroPad\r\n * Create a zero padded string optionally with a radix for casting numbers.\r\n *\r\n * Parameters:\r\n * num - {Number} The number to be zero padded.\r\n * len - {Number} The length of the string to be returned.\r\n * radix - {Number} An integer between 2 and 36 specifying the base to use\r\n * for representing numeric values.\r\n */\r\n zeroPad: function(num, len, radix) {\r\n var str = num.toString(radix || 10);\r\n while (str.length < len) {\r\n str = \"0\" + str;\r\n }\r\n return str;\r\n } \r\n};\r\n\r\n/**\r\n * Namespace: OpenLayers.Function\r\n * Contains convenience functions for function manipulation.\r\n */\r\nOpenLayers.Function = {\r\n /**\r\n * APIFunction: bind\r\n * Bind a function to an object. Method to easily create closures with\r\n * 'this' altered.\r\n * \r\n * Parameters:\r\n * func - {Function} Input function.\r\n * object - {Object} The object to bind to the input function (as this).\r\n * \r\n * Returns:\r\n * {Function} A closure with 'this' set to the passed in object.\r\n */\r\n bind: function(func, object) {\r\n // create a reference to all arguments past the second one\r\n var args = Array.prototype.slice.call(arguments, 2);\r\n return function() {\r\n // Push on any additional arguments from the actual function call.\r\n // These will come after those sent to the bind call.\r\n var newArgs = args.concat(\r\n Array.prototype.slice.call(arguments, 0)\r\n );\r\n return func.apply(object, newArgs);\r\n };\r\n },\r\n \r\n /**\r\n * APIFunction: bindAsEventListener\r\n * Bind a function to an object, and configure it to receive the event\r\n * object as first parameter when called. \r\n * \r\n * Parameters:\r\n * func - {Function} Input function to serve as an event listener.\r\n * object - {Object} A reference to this.\r\n * \r\n * Returns:\r\n * {Function}\r\n */\r\n bindAsEventListener: function(func, object) {\r\n return function(event) {\r\n return func.call(object, event || window.event);\r\n };\r\n },\r\n \r\n /**\r\n * APIFunction: False\r\n * A simple function to that just does \"return false\". We use this to \r\n * avoid attaching anonymous functions to DOM event handlers, which \r\n * causes \"issues\" on IE<8.\r\n * \r\n * Usage:\r\n * document.onclick = OpenLayers.Function.False;\r\n * \r\n * Returns:\r\n * {Boolean}\r\n */\r\n False : function() {\r\n return false;\r\n },\r\n\r\n /**\r\n * APIFunction: True\r\n * A simple function to that just does \"return true\". We use this to \r\n * avoid attaching anonymous functions to DOM event handlers, which \r\n * causes \"issues\" on IE<8.\r\n * \r\n * Usage:\r\n * document.onclick = OpenLayers.Function.True;\r\n * \r\n * Returns:\r\n * {Boolean}\r\n */\r\n True : function() {\r\n return true;\r\n },\r\n \r\n /**\r\n * APIFunction: Void\r\n * A reusable function that returns ``undefined``.\r\n *\r\n * Returns:\r\n * {undefined}\r\n */\r\n Void: function() {}\r\n\r\n};\r\n\r\n/**\r\n * Namespace: OpenLayers.Array\r\n * Contains convenience functions for array manipulation.\r\n */\r\nOpenLayers.Array = {\r\n\r\n /**\r\n * APIMethod: filter\r\n * Filter an array. Provides the functionality of the\r\n * Array.prototype.filter extension to the ECMA-262 standard. Where\r\n * available, Array.prototype.filter will be used.\r\n *\r\n * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter\r\n *\r\n * Parameters:\r\n * array - {Array} The array to be filtered. This array is not mutated.\r\n * Elements added to this array by the callback will not be visited.\r\n * callback - {Function} A function that is called for each element in\r\n * the array. If this function returns true, the element will be\r\n * included in the return. The function will be called with three\r\n * arguments: the element in the array, the index of that element, and\r\n * the array itself. If the optional caller parameter is specified\r\n * the callback will be called with this set to caller.\r\n * caller - {Object} Optional object to be set as this when the callback\r\n * is called.\r\n *\r\n * Returns:\r\n * {Array} An array of elements from the passed in array for which the\r\n * callback returns true.\r\n */\r\n filter: function(array, callback, caller) {\r\n var selected = [];\r\n if (Array.prototype.filter) {\r\n selected = array.filter(callback, caller);\r\n } else {\r\n var len = array.length;\r\n if (typeof callback != \"function\") {\r\n throw new TypeError();\r\n }\r\n for(var i=0; i} A cached center location. This should not be\r\n * accessed directly. Use instead.\r\n */\r\n centerLonLat: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Bounds\r\n * Construct a new bounds object. Coordinates can either be passed as four\r\n * arguments, or as a single argument.\r\n *\r\n * Parameters (four arguments):\r\n * left - {Number} The left bounds of the box. Note that for width\r\n * calculations, this is assumed to be less than the right value.\r\n * bottom - {Number} The bottom bounds of the box. Note that for height\r\n * calculations, this is assumed to be less than the top value.\r\n * right - {Number} The right bounds.\r\n * top - {Number} The top bounds.\r\n *\r\n * Parameters (single argument):\r\n * bounds - {Array(Number)} [left, bottom, right, top]\r\n */\r\n initialize: function(left, bottom, right, top) {\r\n if (OpenLayers.Util.isArray(left)) {\r\n top = left[3];\r\n right = left[2];\r\n bottom = left[1];\r\n left = left[0];\r\n }\r\n if (left != null) {\r\n this.left = OpenLayers.Util.toFloat(left);\r\n }\r\n if (bottom != null) {\r\n this.bottom = OpenLayers.Util.toFloat(bottom);\r\n }\r\n if (right != null) {\r\n this.right = OpenLayers.Util.toFloat(right);\r\n }\r\n if (top != null) {\r\n this.top = OpenLayers.Util.toFloat(top);\r\n }\r\n },\r\n\r\n /**\r\n * Method: clone\r\n * Create a cloned instance of this bounds.\r\n *\r\n * Returns:\r\n * {} A fresh copy of the bounds\r\n */\r\n clone:function() {\r\n return new OpenLayers.Bounds(this.left, this.bottom, \r\n this.right, this.top);\r\n },\r\n\r\n /**\r\n * Method: equals\r\n * Test a two bounds for equivalence.\r\n *\r\n * Parameters:\r\n * bounds - {}\r\n *\r\n * Returns:\r\n * {Boolean} The passed-in bounds object has the same left,\r\n * right, top, bottom components as this. Note that if bounds \r\n * passed in is null, returns false.\r\n */\r\n equals:function(bounds) {\r\n var equals = false;\r\n if (bounds != null) {\r\n equals = ((this.left == bounds.left) && \r\n (this.right == bounds.right) &&\r\n (this.top == bounds.top) && \r\n (this.bottom == bounds.bottom));\r\n }\r\n return equals;\r\n },\r\n\r\n /** \r\n * APIMethod: toString\r\n * Returns a string representation of the bounds object.\r\n * \r\n * Returns:\r\n * {String} String representation of bounds object. \r\n */\r\n toString:function() {\r\n return [this.left, this.bottom, this.right, this.top].join(\",\");\r\n },\r\n\r\n /**\r\n * APIMethod: toArray\r\n * Returns an array representation of the bounds object.\r\n *\r\n * Returns an array of left, bottom, right, top properties, or -- when the\r\n * optional parameter is true -- an array of the bottom, left, top,\r\n * right properties.\r\n *\r\n * Parameters:\r\n * reverseAxisOrder - {Boolean} Should we reverse the axis order?\r\n *\r\n * Returns:\r\n * {Array} array of left, bottom, right, top\r\n */\r\n toArray: function(reverseAxisOrder) {\r\n if (reverseAxisOrder === true) {\r\n return [this.bottom, this.left, this.top, this.right];\r\n } else {\r\n return [this.left, this.bottom, this.right, this.top];\r\n }\r\n }, \r\n\r\n /** \r\n * APIMethod: toBBOX\r\n * Returns a boundingbox-string representation of the bounds object.\r\n * \r\n * Parameters:\r\n * decimal - {Integer} How many decimal places in the bbox coords?\r\n * Default is 6\r\n * reverseAxisOrder - {Boolean} Should we reverse the axis order?\r\n * \r\n * Returns:\r\n * {String} Simple String representation of bounds object.\r\n * (e.g. \"5,42,10,45\")\r\n */\r\n toBBOX:function(decimal, reverseAxisOrder) {\r\n if (decimal== null) {\r\n decimal = 6; \r\n }\r\n var mult = Math.pow(10, decimal);\r\n var xmin = Math.round(this.left * mult) / mult;\r\n var ymin = Math.round(this.bottom * mult) / mult;\r\n var xmax = Math.round(this.right * mult) / mult;\r\n var ymax = Math.round(this.top * mult) / mult;\r\n if (reverseAxisOrder === true) {\r\n return ymin + \",\" + xmin + \",\" + ymax + \",\" + xmax;\r\n } else {\r\n return xmin + \",\" + ymin + \",\" + xmax + \",\" + ymax;\r\n }\r\n },\r\n \r\n /**\r\n * APIMethod: toGeometry\r\n * Create a new polygon geometry based on this bounds.\r\n *\r\n * Returns:\r\n * {} A new polygon with the coordinates\r\n * of this bounds.\r\n */\r\n toGeometry: function() {\r\n return new OpenLayers.Geometry.Polygon([\r\n new OpenLayers.Geometry.LinearRing([\r\n new OpenLayers.Geometry.Point(this.left, this.bottom),\r\n new OpenLayers.Geometry.Point(this.right, this.bottom),\r\n new OpenLayers.Geometry.Point(this.right, this.top),\r\n new OpenLayers.Geometry.Point(this.left, this.top)\r\n ])\r\n ]);\r\n },\r\n \r\n /**\r\n * APIMethod: getWidth\r\n * Returns the width of the bounds.\r\n * \r\n * Returns:\r\n * {Float} The width of the bounds (right minus left).\r\n */\r\n getWidth:function() {\r\n return (this.right - this.left);\r\n },\r\n\r\n /**\r\n * APIMethod: getHeight\r\n * Returns the height of the bounds.\r\n * \r\n * Returns:\r\n * {Float} The height of the bounds (top minus bottom).\r\n */\r\n getHeight:function() {\r\n return (this.top - this.bottom);\r\n },\r\n\r\n /**\r\n * APIMethod: getSize\r\n * Returns an object of the bounds.\r\n * \r\n * Returns:\r\n * {} The size of the bounds.\r\n */\r\n getSize:function() {\r\n return new OpenLayers.Size(this.getWidth(), this.getHeight());\r\n },\r\n\r\n /**\r\n * APIMethod: getCenterPixel\r\n * Returns the object which represents the center of the\r\n * bounds.\r\n * \r\n * Returns:\r\n * {} The center of the bounds in pixel space.\r\n */\r\n getCenterPixel:function() {\r\n return new OpenLayers.Pixel( (this.left + this.right) / 2,\r\n (this.bottom + this.top) / 2);\r\n },\r\n\r\n /**\r\n * APIMethod: getCenterLonLat\r\n * Returns the object which represents the center of the\r\n * bounds.\r\n *\r\n * Returns:\r\n * {} The center of the bounds in map space.\r\n */\r\n getCenterLonLat:function() {\r\n if(!this.centerLonLat) {\r\n this.centerLonLat = new OpenLayers.LonLat(\r\n (this.left + this.right) / 2, (this.bottom + this.top) / 2\r\n );\r\n }\r\n return this.centerLonLat;\r\n },\r\n\r\n /**\r\n * APIMethod: scale\r\n * Scales the bounds around a pixel or lonlat. Note that the new \r\n * bounds may return non-integer properties, even if a pixel\r\n * is passed. \r\n * \r\n * Parameters:\r\n * ratio - {Float} \r\n * origin - { or }\r\n * Default is center.\r\n *\r\n * Returns:\r\n * {} A new bounds that is scaled by ratio\r\n * from origin.\r\n */\r\n scale: function(ratio, origin){\r\n if(origin == null){\r\n origin = this.getCenterLonLat();\r\n }\r\n \r\n var origx,origy;\r\n\r\n // get origin coordinates\r\n if(origin.CLASS_NAME == \"OpenLayers.LonLat\"){\r\n origx = origin.lon;\r\n origy = origin.lat;\r\n } else {\r\n origx = origin.x;\r\n origy = origin.y;\r\n }\r\n\r\n var left = (this.left - origx) * ratio + origx;\r\n var bottom = (this.bottom - origy) * ratio + origy;\r\n var right = (this.right - origx) * ratio + origx;\r\n var top = (this.top - origy) * ratio + origy;\r\n \r\n return new OpenLayers.Bounds(left, bottom, right, top);\r\n },\r\n\r\n /**\r\n * APIMethod: add\r\n * Shifts the coordinates of the bound by the given horizontal and vertical\r\n * deltas.\r\n *\r\n * (start code)\r\n * var bounds = new OpenLayers.Bounds(0, 0, 10, 10);\r\n * bounds.toString();\r\n * // => \"0,0,10,10\"\r\n *\r\n * bounds.add(-1.5, 4).toString();\r\n * // => \"-1.5,4,8.5,14\"\r\n * (end)\r\n *\r\n * This method will throw a TypeError if it is passed null as an argument.\r\n *\r\n * Parameters:\r\n * x - {Float} horizontal delta\r\n * y - {Float} vertical delta\r\n *\r\n * Returns:\r\n * {} A new bounds whose coordinates are the same as\r\n * this, but shifted by the passed-in x and y values.\r\n */\r\n add:function(x, y) {\r\n if ( (x == null) || (y == null) ) {\r\n throw new TypeError('Bounds.add cannot receive null values');\r\n }\r\n return new OpenLayers.Bounds(this.left + x, this.bottom + y,\r\n this.right + x, this.top + y);\r\n },\r\n \r\n /**\r\n * APIMethod: extend\r\n * Extend the bounds to include the ,\r\n * or specified.\r\n *\r\n * Please note that this function assumes that left < right and\r\n * bottom < top.\r\n *\r\n * Parameters:\r\n * object - {, or\r\n * } The object to be included in the new bounds\r\n * object.\r\n */\r\n extend:function(object) {\r\n if (object) {\r\n switch(object.CLASS_NAME) {\r\n case \"OpenLayers.LonLat\":\r\n this.extendXY(object.lon, object.lat);\r\n break;\r\n case \"OpenLayers.Geometry.Point\":\r\n this.extendXY(object.x, object.y);\r\n break;\r\n\r\n case \"OpenLayers.Bounds\":\r\n // clear cached center location\r\n this.centerLonLat = null;\r\n\r\n if ( (this.left == null) || (object.left < this.left)) {\r\n this.left = object.left;\r\n }\r\n if ( (this.bottom == null) || (object.bottom < this.bottom) ) {\r\n this.bottom = object.bottom;\r\n }\r\n if ( (this.right == null) || (object.right > this.right) ) {\r\n this.right = object.right;\r\n }\r\n if ( (this.top == null) || (object.top > this.top) ) {\r\n this.top = object.top;\r\n }\r\n break;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: extendXY\r\n * Extend the bounds to include the XY coordinate specified.\r\n *\r\n * Parameters:\r\n * x - {number} The X part of the the coordinate.\r\n * y - {number} The Y part of the the coordinate.\r\n */\r\n extendXY:function(x, y) {\r\n // clear cached center location\r\n this.centerLonLat = null;\r\n\r\n if ((this.left == null) || (x < this.left)) {\r\n this.left = x;\r\n }\r\n if ((this.bottom == null) || (y < this.bottom)) {\r\n this.bottom = y;\r\n }\r\n if ((this.right == null) || (x > this.right)) {\r\n this.right = x;\r\n }\r\n if ((this.top == null) || (y > this.top)) {\r\n this.top = y;\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: containsLonLat\r\n * Returns whether the bounds object contains the given .\r\n * \r\n * Parameters:\r\n * ll - {|Object} OpenLayers.LonLat or an\r\n * object with a 'lon' and 'lat' properties.\r\n * options - {Object} Optional parameters\r\n *\r\n * Acceptable options:\r\n * inclusive - {Boolean} Whether or not to include the border.\r\n * Default is true.\r\n * worldBounds - {} If a worldBounds is provided, the\r\n * ll will be considered as contained if it exceeds the world bounds,\r\n * but can be wrapped around the dateline so it is contained by this\r\n * bounds.\r\n *\r\n * Returns:\r\n * {Boolean} The passed-in lonlat is within this bounds.\r\n */\r\n containsLonLat: function(ll, options) {\r\n if (typeof options === \"boolean\") {\r\n options = {inclusive: options};\r\n }\r\n options = options || {};\r\n var contains = this.contains(ll.lon, ll.lat, options.inclusive),\r\n worldBounds = options.worldBounds;\r\n if (worldBounds && !contains) {\r\n var worldWidth = worldBounds.getWidth();\r\n var worldCenterX = (worldBounds.left + worldBounds.right) / 2;\r\n var worldsAway = Math.round((ll.lon - worldCenterX) / worldWidth);\r\n contains = this.containsLonLat({\r\n lon: ll.lon - worldsAway * worldWidth,\r\n lat: ll.lat\r\n }, {inclusive: options.inclusive});\r\n }\r\n return contains;\r\n },\r\n\r\n /**\r\n * APIMethod: containsPixel\r\n * Returns whether the bounds object contains the given .\r\n * \r\n * Parameters:\r\n * px - {}\r\n * inclusive - {Boolean} Whether or not to include the border. Default is\r\n * true.\r\n *\r\n * Returns:\r\n * {Boolean} The passed-in pixel is within this bounds.\r\n */\r\n containsPixel:function(px, inclusive) {\r\n return this.contains(px.x, px.y, inclusive);\r\n },\r\n \r\n /**\r\n * APIMethod: contains\r\n * Returns whether the bounds object contains the given x and y.\r\n * \r\n * Parameters:\r\n * x - {Float}\r\n * y - {Float}\r\n * inclusive - {Boolean} Whether or not to include the border. Default is\r\n * true.\r\n *\r\n * Returns:\r\n * {Boolean} Whether or not the passed-in coordinates are within this\r\n * bounds.\r\n */\r\n contains:function(x, y, inclusive) {\r\n //set default\r\n if (inclusive == null) {\r\n inclusive = true;\r\n }\r\n\r\n if (x == null || y == null) {\r\n return false;\r\n }\r\n\r\n x = OpenLayers.Util.toFloat(x);\r\n y = OpenLayers.Util.toFloat(y);\r\n\r\n var contains = false;\r\n if (inclusive) {\r\n contains = ((x >= this.left) && (x <= this.right) && \r\n (y >= this.bottom) && (y <= this.top));\r\n } else {\r\n contains = ((x > this.left) && (x < this.right) && \r\n (y > this.bottom) && (y < this.top));\r\n } \r\n return contains;\r\n },\r\n\r\n /**\r\n * APIMethod: intersectsBounds\r\n * Determine whether the target bounds intersects this bounds. Bounds are\r\n * considered intersecting if any of their edges intersect or if one\r\n * bounds contains the other.\r\n * \r\n * Parameters:\r\n * bounds - {} The target bounds.\r\n * options - {Object} Optional parameters.\r\n * \r\n * Acceptable options:\r\n * inclusive - {Boolean} Treat coincident borders as intersecting. Default\r\n * is true. If false, bounds that do not overlap but only touch at the\r\n * border will not be considered as intersecting.\r\n * worldBounds - {} If a worldBounds is provided, two\r\n * bounds will be considered as intersecting if they intersect when \r\n * shifted to within the world bounds. This applies only to bounds that\r\n * cross or are completely outside the world bounds.\r\n *\r\n * Returns:\r\n * {Boolean} The passed-in bounds object intersects this bounds.\r\n */\r\n intersectsBounds:function(bounds, options) {\r\n if (typeof options === \"boolean\") {\r\n options = {inclusive: options};\r\n }\r\n options = options || {};\r\n if (options.worldBounds) {\r\n var self = this.wrapDateLine(options.worldBounds);\r\n bounds = bounds.wrapDateLine(options.worldBounds);\r\n } else {\r\n self = this;\r\n }\r\n if (options.inclusive == null) {\r\n options.inclusive = true;\r\n }\r\n var intersects = false;\r\n var mightTouch = (\r\n self.left == bounds.right ||\r\n self.right == bounds.left ||\r\n self.top == bounds.bottom ||\r\n self.bottom == bounds.top\r\n );\r\n \r\n // if the two bounds only touch at an edge, and inclusive is false,\r\n // then the bounds don't *really* intersect.\r\n if (options.inclusive || !mightTouch) {\r\n // otherwise, if one of the boundaries even partially contains another,\r\n // inclusive of the edges, then they do intersect.\r\n var inBottom = (\r\n ((bounds.bottom >= self.bottom) && (bounds.bottom <= self.top)) ||\r\n ((self.bottom >= bounds.bottom) && (self.bottom <= bounds.top))\r\n );\r\n var inTop = (\r\n ((bounds.top >= self.bottom) && (bounds.top <= self.top)) ||\r\n ((self.top > bounds.bottom) && (self.top < bounds.top))\r\n );\r\n var inLeft = (\r\n ((bounds.left >= self.left) && (bounds.left <= self.right)) ||\r\n ((self.left >= bounds.left) && (self.left <= bounds.right))\r\n );\r\n var inRight = (\r\n ((bounds.right >= self.left) && (bounds.right <= self.right)) ||\r\n ((self.right >= bounds.left) && (self.right <= bounds.right))\r\n );\r\n intersects = ((inBottom || inTop) && (inLeft || inRight));\r\n }\r\n // document me\r\n if (options.worldBounds && !intersects) {\r\n var world = options.worldBounds;\r\n var width = world.getWidth();\r\n var selfCrosses = !world.containsBounds(self);\r\n var boundsCrosses = !world.containsBounds(bounds);\r\n if (selfCrosses && !boundsCrosses) {\r\n bounds = bounds.add(-width, 0);\r\n intersects = self.intersectsBounds(bounds, {inclusive: options.inclusive});\r\n } else if (boundsCrosses && !selfCrosses) {\r\n self = self.add(-width, 0);\r\n intersects = bounds.intersectsBounds(self, {inclusive: options.inclusive}); \r\n }\r\n }\r\n return intersects;\r\n },\r\n \r\n /**\r\n * APIMethod: containsBounds\r\n * Returns whether the bounds object contains the given .\r\n * \r\n * bounds - {} The target bounds.\r\n * partial - {Boolean} If any of the target corners is within this bounds\r\n * consider the bounds contained. Default is false. If false, the\r\n * entire target bounds must be contained within this bounds.\r\n * inclusive - {Boolean} Treat shared edges as contained. Default is\r\n * true.\r\n *\r\n * Returns:\r\n * {Boolean} The passed-in bounds object is contained within this bounds. \r\n */\r\n containsBounds:function(bounds, partial, inclusive) {\r\n if (partial == null) {\r\n partial = false;\r\n }\r\n if (inclusive == null) {\r\n inclusive = true;\r\n }\r\n var bottomLeft = this.contains(bounds.left, bounds.bottom, inclusive);\r\n var bottomRight = this.contains(bounds.right, bounds.bottom, inclusive);\r\n var topLeft = this.contains(bounds.left, bounds.top, inclusive);\r\n var topRight = this.contains(bounds.right, bounds.top, inclusive);\r\n \r\n return (partial) ? (bottomLeft || bottomRight || topLeft || topRight)\r\n : (bottomLeft && bottomRight && topLeft && topRight);\r\n },\r\n\r\n /** \r\n * APIMethod: determineQuadrant\r\n * Returns the the quadrant (\"br\", \"tr\", \"tl\", \"bl\") in which the given\r\n * lies.\r\n *\r\n * Parameters:\r\n * lonlat - {}\r\n *\r\n * Returns:\r\n * {String} The quadrant (\"br\" \"tr\" \"tl\" \"bl\") of the bounds in which the\r\n * coordinate lies.\r\n */\r\n determineQuadrant: function(lonlat) {\r\n \r\n var quadrant = \"\";\r\n var center = this.getCenterLonLat();\r\n \r\n quadrant += (lonlat.lat < center.lat) ? \"b\" : \"t\";\r\n quadrant += (lonlat.lon < center.lon) ? \"l\" : \"r\";\r\n \r\n return quadrant; \r\n },\r\n \r\n /**\r\n * APIMethod: transform\r\n * Transform the Bounds object from source to dest. \r\n *\r\n * Parameters: \r\n * source - {} Source projection. \r\n * dest - {} Destination projection. \r\n *\r\n * Returns:\r\n * {} Itself, for use in chaining operations.\r\n */\r\n transform: function(source, dest) {\r\n // clear cached center location\r\n this.centerLonLat = null;\r\n var ll = OpenLayers.Projection.transform(\r\n {'x': this.left, 'y': this.bottom}, source, dest);\r\n var lr = OpenLayers.Projection.transform(\r\n {'x': this.right, 'y': this.bottom}, source, dest);\r\n var ul = OpenLayers.Projection.transform(\r\n {'x': this.left, 'y': this.top}, source, dest);\r\n var ur = OpenLayers.Projection.transform(\r\n {'x': this.right, 'y': this.top}, source, dest);\r\n this.left = Math.min(ll.x, ul.x);\r\n this.bottom = Math.min(ll.y, lr.y);\r\n this.right = Math.max(lr.x, ur.x);\r\n this.top = Math.max(ul.y, ur.y);\r\n return this;\r\n },\r\n\r\n /**\r\n * APIMethod: wrapDateLine\r\n * Wraps the bounds object around the dateline.\r\n * \r\n * Parameters:\r\n * maxExtent - {}\r\n * options - {Object} Some possible options are:\r\n *\r\n * Allowed Options:\r\n * leftTolerance - {float} Allow for a margin of error \r\n * with the 'left' value of this \r\n * bound.\r\n * Default is 0.\r\n * rightTolerance - {float} Allow for a margin of error \r\n * with the 'right' value of \r\n * this bound.\r\n * Default is 0.\r\n * \r\n * Returns:\r\n * {} A copy of this bounds, but wrapped around the \r\n * \"dateline\" (as specified by the borders of \r\n * maxExtent). Note that this function only returns \r\n * a different bounds value if this bounds is \r\n * *entirely* outside of the maxExtent. If this \r\n * bounds straddles the dateline (is part in/part \r\n * out of maxExtent), the returned bounds will always \r\n * cross the left edge of the given maxExtent.\r\n *.\r\n */\r\n wrapDateLine: function(maxExtent, options) { \r\n options = options || {};\r\n \r\n var leftTolerance = options.leftTolerance || 0;\r\n var rightTolerance = options.rightTolerance || 0;\r\n\r\n var newBounds = this.clone();\r\n \r\n if (maxExtent) {\r\n var width = maxExtent.getWidth();\r\n\r\n //shift right?\r\n while (newBounds.left < maxExtent.left && \r\n newBounds.right - rightTolerance <= maxExtent.left ) { \r\n newBounds = newBounds.add(width, 0);\r\n }\r\n\r\n //shift left?\r\n while (newBounds.left + leftTolerance >= maxExtent.right && \r\n newBounds.right > maxExtent.right ) { \r\n newBounds = newBounds.add(-width, 0);\r\n }\r\n \r\n // crosses right only? force left\r\n var newLeft = newBounds.left + leftTolerance;\r\n if (newLeft < maxExtent.right && newLeft > maxExtent.left && \r\n newBounds.right - rightTolerance > maxExtent.right) {\r\n newBounds = newBounds.add(-width, 0);\r\n }\r\n }\r\n \r\n return newBounds;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Bounds\"\r\n});\r\n\r\n/** \r\n * APIFunction: fromString\r\n * Alternative constructor that builds a new OpenLayers.Bounds from a \r\n * parameter string.\r\n *\r\n * (begin code)\r\n * OpenLayers.Bounds.fromString(\"5,42,10,45\");\r\n * // => equivalent to ...\r\n * new OpenLayers.Bounds(5, 42, 10, 45);\r\n * (end)\r\n *\r\n * Parameters: \r\n * str - {String} Comma-separated bounds string. (e.g. \"5,42,10,45\")\r\n * reverseAxisOrder - {Boolean} Does the string use reverse axis order?\r\n *\r\n * Returns:\r\n * {} New bounds object built from the \r\n * passed-in String.\r\n */\r\nOpenLayers.Bounds.fromString = function(str, reverseAxisOrder) {\r\n var bounds = str.split(\",\");\r\n return OpenLayers.Bounds.fromArray(bounds, reverseAxisOrder);\r\n};\r\n\r\n/** \r\n * APIFunction: fromArray\r\n * Alternative constructor that builds a new OpenLayers.Bounds from an array.\r\n *\r\n * (begin code)\r\n * OpenLayers.Bounds.fromArray( [5, 42, 10, 45] );\r\n * // => equivalent to ...\r\n * new OpenLayers.Bounds(5, 42, 10, 45);\r\n * (end)\r\n *\r\n * Parameters:\r\n * bbox - {Array(Float)} Array of bounds values (e.g. [5,42,10,45])\r\n * reverseAxisOrder - {Boolean} Does the array use reverse axis order?\r\n *\r\n * Returns:\r\n * {} New bounds object built from the passed-in Array.\r\n */\r\nOpenLayers.Bounds.fromArray = function(bbox, reverseAxisOrder) {\r\n return reverseAxisOrder === true ?\r\n new OpenLayers.Bounds(bbox[1], bbox[0], bbox[3], bbox[2]) :\r\n new OpenLayers.Bounds(bbox[0], bbox[1], bbox[2], bbox[3]);\r\n};\r\n\r\n/** \r\n * APIFunction: fromSize\r\n * Alternative constructor that builds a new OpenLayers.Bounds from a size.\r\n *\r\n * (begin code)\r\n * OpenLayers.Bounds.fromSize( new OpenLayers.Size(10, 20) );\r\n * // => equivalent to ...\r\n * new OpenLayers.Bounds(0, 20, 10, 0);\r\n * (end)\r\n *\r\n * Parameters:\r\n * size - { or Object} or an object with\r\n * both 'w' and 'h' properties.\r\n *\r\n * Returns:\r\n * {} New bounds object built from the passed-in size.\r\n */\r\nOpenLayers.Bounds.fromSize = function(size) {\r\n return new OpenLayers.Bounds(0,\r\n size.h,\r\n size.w,\r\n 0);\r\n};\r\n\r\n/**\r\n * Function: oppositeQuadrant\r\n * Get the opposite quadrant for a given quadrant string.\r\n *\r\n * (begin code)\r\n * OpenLayers.Bounds.oppositeQuadrant( \"tl\" );\r\n * // => \"br\"\r\n *\r\n * OpenLayers.Bounds.oppositeQuadrant( \"tr\" );\r\n * // => \"bl\"\r\n * (end)\r\n *\r\n * Parameters:\r\n * quadrant - {String} two character quadrant shortstring\r\n *\r\n * Returns:\r\n * {String} The opposing quadrant (\"br\" \"tr\" \"tl\" \"bl\"). For Example, if \r\n * you pass in \"bl\" it returns \"tr\", if you pass in \"br\" it \r\n * returns \"tl\", etc.\r\n */\r\nOpenLayers.Bounds.oppositeQuadrant = function(quadrant) {\r\n var opp = \"\";\r\n \r\n opp += (quadrant.charAt(0) == 't') ? 'b' : 't';\r\n opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l';\r\n \r\n return opp;\r\n};\r\n/* ======================================================================\r\n OpenLayers/BaseTypes/Element.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Util.js\r\n * @requires OpenLayers/BaseTypes.js\r\n */\r\n\r\n/**\r\n * Namespace: OpenLayers.Element\r\n */\r\nOpenLayers.Element = {\r\n\r\n /**\r\n * APIFunction: visible\r\n * \r\n * Parameters: \r\n * element - {DOMElement}\r\n * \r\n * Returns:\r\n * {Boolean} Is the element visible?\r\n */\r\n visible: function(element) {\r\n return OpenLayers.Util.getElement(element).style.display != 'none';\r\n },\r\n\r\n /**\r\n * APIFunction: toggle\r\n * Toggle the visibility of element(s) passed in\r\n * \r\n * Parameters:\r\n * element - {DOMElement} Actually user can pass any number of elements\r\n */\r\n toggle: function() {\r\n for (var i=0, len=arguments.length; i\"lon=5,lat=42\")\r\n */\r\n toString:function() {\r\n return (\"lon=\" + this.lon + \",lat=\" + this.lat);\r\n },\r\n\r\n /** \r\n * APIMethod: toShortString\r\n * \r\n * Returns:\r\n * {String} Shortened String representation of OpenLayers.LonLat object. \r\n * (e.g. \"5, 42\")\r\n */\r\n toShortString:function() {\r\n return (this.lon + \", \" + this.lat);\r\n },\r\n\r\n /** \r\n * APIMethod: clone\r\n * \r\n * Returns:\r\n * {} New OpenLayers.LonLat object with the same lon \r\n * and lat values\r\n */\r\n clone:function() {\r\n return new OpenLayers.LonLat(this.lon, this.lat);\r\n },\r\n\r\n /** \r\n * APIMethod: add\r\n * \r\n * Parameters:\r\n * lon - {Float}\r\n * lat - {Float}\r\n * \r\n * Returns:\r\n * {} A new OpenLayers.LonLat object with the lon and \r\n * lat passed-in added to this's. \r\n */\r\n add:function(lon, lat) {\r\n if ( (lon == null) || (lat == null) ) {\r\n throw new TypeError('LonLat.add cannot receive null values');\r\n }\r\n return new OpenLayers.LonLat(this.lon + OpenLayers.Util.toFloat(lon), \r\n this.lat + OpenLayers.Util.toFloat(lat));\r\n },\r\n\r\n /** \r\n * APIMethod: equals\r\n * \r\n * Parameters:\r\n * ll - {}\r\n * \r\n * Returns:\r\n * {Boolean} Boolean value indicating whether the passed-in \r\n * object has the same lon and lat \r\n * components as this.\r\n * Note: if ll passed in is null, returns false\r\n */\r\n equals:function(ll) {\r\n var equals = false;\r\n if (ll != null) {\r\n equals = ((this.lon == ll.lon && this.lat == ll.lat) ||\r\n (isNaN(this.lon) && isNaN(this.lat) && isNaN(ll.lon) && isNaN(ll.lat)));\r\n }\r\n return equals;\r\n },\r\n\r\n /**\r\n * APIMethod: transform\r\n * Transform the LonLat object from source to dest. This transformation is\r\n * *in place*: if you want a *new* lonlat, use .clone() first.\r\n *\r\n * Parameters: \r\n * source - {} Source projection. \r\n * dest - {} Destination projection. \r\n *\r\n * Returns:\r\n * {} Itself, for use in chaining operations.\r\n */\r\n transform: function(source, dest) {\r\n var point = OpenLayers.Projection.transform(\r\n {'x': this.lon, 'y': this.lat}, source, dest);\r\n this.lon = point.x;\r\n this.lat = point.y;\r\n return this;\r\n },\r\n \r\n /**\r\n * APIMethod: wrapDateLine\r\n * \r\n * Parameters:\r\n * maxExtent - {}\r\n * \r\n * Returns:\r\n * {} A copy of this lonlat, but wrapped around the \r\n * \"dateline\" (as specified by the borders of \r\n * maxExtent)\r\n */\r\n wrapDateLine: function(maxExtent) { \r\n\r\n var newLonLat = this.clone();\r\n \r\n if (maxExtent) {\r\n //shift right?\r\n while (newLonLat.lon < maxExtent.left) {\r\n newLonLat.lon += maxExtent.getWidth();\r\n } \r\n \r\n //shift left?\r\n while (newLonLat.lon > maxExtent.right) {\r\n newLonLat.lon -= maxExtent.getWidth();\r\n } \r\n }\r\n \r\n return newLonLat;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.LonLat\"\r\n});\r\n\r\n/** \r\n * Function: fromString\r\n * Alternative constructor that builds a new from a \r\n * parameter string\r\n * \r\n * Parameters:\r\n * str - {String} Comma-separated Lon,Lat coordinate string. \r\n * (e.g. \"5,40\")\r\n * \r\n * Returns:\r\n * {} New object built from the \r\n * passed-in String.\r\n */\r\nOpenLayers.LonLat.fromString = function(str) {\r\n var pair = str.split(\",\");\r\n return new OpenLayers.LonLat(pair[0], pair[1]);\r\n};\r\n\r\n/** \r\n * Function: fromArray\r\n * Alternative constructor that builds a new from an \r\n * array of two numbers that represent lon- and lat-values.\r\n * \r\n * Parameters:\r\n * arr - {Array(Float)} Array of lon/lat values (e.g. [5,-42])\r\n * \r\n * Returns:\r\n * {} New object built from the \r\n * passed-in array.\r\n */\r\nOpenLayers.LonLat.fromArray = function(arr) {\r\n var gotArr = OpenLayers.Util.isArray(arr),\r\n lon = gotArr && arr[0],\r\n lat = gotArr && arr[1];\r\n return new OpenLayers.LonLat(lon, lat);\r\n};\r\n/* ======================================================================\r\n OpenLayers/BaseTypes/Pixel.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Pixel\r\n * This class represents a screen coordinate, in x and y coordinates\r\n */\r\nOpenLayers.Pixel = OpenLayers.Class({\r\n \r\n /**\r\n * APIProperty: x\r\n * {Number} The x coordinate\r\n */\r\n x: 0.0,\r\n\r\n /**\r\n * APIProperty: y\r\n * {Number} The y coordinate\r\n */\r\n y: 0.0,\r\n \r\n /**\r\n * Constructor: OpenLayers.Pixel\r\n * Create a new OpenLayers.Pixel instance\r\n *\r\n * Parameters:\r\n * x - {Number} The x coordinate\r\n * y - {Number} The y coordinate\r\n *\r\n * Returns:\r\n * An instance of OpenLayers.Pixel\r\n */\r\n initialize: function(x, y) {\r\n this.x = parseFloat(x);\r\n this.y = parseFloat(y);\r\n },\r\n \r\n /**\r\n * Method: toString\r\n * Cast this object into a string\r\n *\r\n * Returns:\r\n * {String} The string representation of Pixel. ex: \"x=200.4,y=242.2\"\r\n */\r\n toString:function() {\r\n return (\"x=\" + this.x + \",y=\" + this.y);\r\n },\r\n\r\n /**\r\n * APIMethod: clone\r\n * Return a clone of this pixel object\r\n *\r\n * Returns:\r\n * {} A clone pixel\r\n */\r\n clone:function() {\r\n return new OpenLayers.Pixel(this.x, this.y); \r\n },\r\n \r\n /**\r\n * APIMethod: equals\r\n * Determine whether one pixel is equivalent to another\r\n *\r\n * Parameters:\r\n * px - {|Object} An OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n *\r\n * Returns:\r\n * {Boolean} The point passed in as parameter is equal to this. Note that\r\n * if px passed in is null, returns false.\r\n */\r\n equals:function(px) {\r\n var equals = false;\r\n if (px != null) {\r\n equals = ((this.x == px.x && this.y == px.y) ||\r\n (isNaN(this.x) && isNaN(this.y) && isNaN(px.x) && isNaN(px.y)));\r\n }\r\n return equals;\r\n },\r\n\r\n /**\r\n * APIMethod: distanceTo\r\n * Returns the distance to the pixel point passed in as a parameter.\r\n *\r\n * Parameters:\r\n * px - {}\r\n *\r\n * Returns:\r\n * {Float} The pixel point passed in as parameter to calculate the\r\n * distance to.\r\n */\r\n distanceTo:function(px) {\r\n return Math.sqrt(\r\n Math.pow(this.x - px.x, 2) +\r\n Math.pow(this.y - px.y, 2)\r\n );\r\n },\r\n\r\n /**\r\n * APIMethod: add\r\n *\r\n * Parameters:\r\n * x - {Integer}\r\n * y - {Integer}\r\n *\r\n * Returns:\r\n * {} A new Pixel with this pixel's x&y augmented by the \r\n * values passed in.\r\n */\r\n add:function(x, y) {\r\n if ( (x == null) || (y == null) ) {\r\n throw new TypeError('Pixel.add cannot receive null values');\r\n }\r\n return new OpenLayers.Pixel(this.x + x, this.y + y);\r\n },\r\n\r\n /**\r\n * APIMethod: offset\r\n * \r\n * Parameters\r\n * px - {|Object} An OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * \r\n * Returns:\r\n * {} A new Pixel with this pixel's x&y augmented by the \r\n * x&y values of the pixel passed in.\r\n */\r\n offset:function(px) {\r\n var newPx = this.clone();\r\n if (px) {\r\n newPx = this.add(px.x, px.y);\r\n }\r\n return newPx;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Pixel\"\r\n});\r\n/* ======================================================================\r\n OpenLayers/BaseTypes/Size.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Size\r\n * Instances of this class represent a width/height pair\r\n */\r\nOpenLayers.Size = OpenLayers.Class({\r\n\r\n /**\r\n * APIProperty: w\r\n * {Number} width\r\n */\r\n w: 0.0,\r\n \r\n /**\r\n * APIProperty: h\r\n * {Number} height\r\n */\r\n h: 0.0,\r\n\r\n\r\n /**\r\n * Constructor: OpenLayers.Size\r\n * Create an instance of OpenLayers.Size\r\n *\r\n * Parameters:\r\n * w - {Number} width\r\n * h - {Number} height\r\n */\r\n initialize: function(w, h) {\r\n this.w = parseFloat(w);\r\n this.h = parseFloat(h);\r\n },\r\n\r\n /**\r\n * Method: toString\r\n * Return the string representation of a size object\r\n *\r\n * Returns:\r\n * {String} The string representation of OpenLayers.Size object. \r\n * (e.g. \"w=55,h=66\")\r\n */\r\n toString:function() {\r\n return (\"w=\" + this.w + \",h=\" + this.h);\r\n },\r\n\r\n /**\r\n * APIMethod: clone\r\n * Create a clone of this size object\r\n *\r\n * Returns:\r\n * {} A new OpenLayers.Size object with the same w and h\r\n * values\r\n */\r\n clone:function() {\r\n return new OpenLayers.Size(this.w, this.h);\r\n },\r\n\r\n /**\r\n *\r\n * APIMethod: equals\r\n * Determine where this size is equal to another\r\n *\r\n * Parameters:\r\n * sz - {|Object} An OpenLayers.Size or an object with\r\n * a 'w' and 'h' properties.\r\n *\r\n * Returns: \r\n * {Boolean} The passed in size has the same h and w properties as this one.\r\n * Note that if sz passed in is null, returns false.\r\n */\r\n equals:function(sz) {\r\n var equals = false;\r\n if (sz != null) {\r\n equals = ((this.w == sz.w && this.h == sz.h) ||\r\n (isNaN(this.w) && isNaN(this.h) && isNaN(sz.w) && isNaN(sz.h)));\r\n }\r\n return equals;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Size\"\r\n});\r\n/* ======================================================================\r\n OpenLayers/Console.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n */\r\n\r\n/**\r\n * Namespace: OpenLayers.Console\r\n * The OpenLayers.Console namespace is used for debugging and error logging.\r\n * If the Firebug Lite (../Firebug/firebug.js) is included before this script,\r\n * calls to OpenLayers.Console methods will get redirected to window.console.\r\n * This makes use of the Firebug extension where available and allows for\r\n * cross-browser debugging Firebug style.\r\n *\r\n * Note:\r\n * Note that behavior will differ with the Firebug extension and Firebug Lite.\r\n * Most notably, the Firebug Lite console does not currently allow for\r\n * hyperlinks to code or for clicking on object to explore their properties.\r\n * \r\n */\r\nOpenLayers.Console = {\r\n /**\r\n * Create empty functions for all console methods. The real value of these\r\n * properties will be set if Firebug Lite (../Firebug/firebug.js script) is\r\n * included. We explicitly require the Firebug Lite script to trigger\r\n * functionality of the OpenLayers.Console methods.\r\n */\r\n \r\n /**\r\n * APIFunction: log\r\n * Log an object in the console. The Firebug Lite console logs string\r\n * representation of objects. Given multiple arguments, they will\r\n * be cast to strings and logged with a space delimiter. If the first\r\n * argument is a string with printf-like formatting, subsequent arguments\r\n * will be used in string substitution. Any additional arguments (beyond\r\n * the number substituted in a format string) will be appended in a space-\r\n * delimited line.\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n log: function() {},\r\n\r\n /**\r\n * APIFunction: debug\r\n * Writes a message to the console, including a hyperlink to the line\r\n * where it was called.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n debug: function() {},\r\n\r\n /**\r\n * APIFunction: info\r\n * Writes a message to the console with the visual \"info\" icon and color\r\n * coding and a hyperlink to the line where it was called.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n info: function() {},\r\n\r\n /**\r\n * APIFunction: warn\r\n * Writes a message to the console with the visual \"warning\" icon and\r\n * color coding and a hyperlink to the line where it was called.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n warn: function() {},\r\n\r\n /**\r\n * APIFunction: error\r\n * Writes a message to the console with the visual \"error\" icon and color\r\n * coding and a hyperlink to the line where it was called.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n error: function() {},\r\n \r\n /**\r\n * APIFunction: userError\r\n * A single interface for showing error messages to the user. The default\r\n * behavior is a Javascript alert, though this can be overridden by\r\n * reassigning OpenLayers.Console.userError to a different function.\r\n *\r\n * Expects a single error message\r\n * \r\n * Parameters:\r\n * error - {Object}\r\n */\r\n userError: function(error) {\r\n alert(error);\r\n },\r\n\r\n /**\r\n * APIFunction: assert\r\n * Tests that an expression is true. If not, it will write a message to\r\n * the console and throw an exception.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n assert: function() {},\r\n\r\n /**\r\n * APIFunction: dir\r\n * Prints an interactive listing of all properties of the object. This\r\n * looks identical to the view that you would see in the DOM tab.\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n dir: function() {},\r\n\r\n /**\r\n * APIFunction: dirxml\r\n * Prints the XML source tree of an HTML or XML element. This looks\r\n * identical to the view that you would see in the HTML tab. You can click\r\n * on any node to inspect it in the HTML tab.\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n dirxml: function() {},\r\n\r\n /**\r\n * APIFunction: trace\r\n * Prints an interactive stack trace of JavaScript execution at the point\r\n * where it is called. The stack trace details the functions on the stack,\r\n * as well as the values that were passed as arguments to each function.\r\n * You can click each function to take you to its source in the Script tab,\r\n * and click each argument value to inspect it in the DOM or HTML tabs.\r\n * \r\n */\r\n trace: function() {},\r\n\r\n /**\r\n * APIFunction: group\r\n * Writes a message to the console and opens a nested block to indent all\r\n * future messages sent to the console. Call OpenLayers.Console.groupEnd()\r\n * to close the block.\r\n *\r\n * May be called with multiple arguments as with OpenLayers.Console.log().\r\n * \r\n * Parameters:\r\n * object - {Object}\r\n */\r\n group: function() {},\r\n\r\n /**\r\n * APIFunction: groupEnd\r\n * Closes the most recently opened block created by a call to\r\n * OpenLayers.Console.group\r\n */\r\n groupEnd: function() {},\r\n \r\n /**\r\n * APIFunction: time\r\n * Creates a new timer under the given name. Call\r\n * OpenLayers.Console.timeEnd(name)\r\n * with the same name to stop the timer and print the time elapsed.\r\n *\r\n * Parameters:\r\n * name - {String}\r\n */\r\n time: function() {},\r\n\r\n /**\r\n * APIFunction: timeEnd\r\n * Stops a timer created by a call to OpenLayers.Console.time(name) and\r\n * writes the time elapsed.\r\n *\r\n * Parameters:\r\n * name - {String}\r\n */\r\n timeEnd: function() {},\r\n\r\n /**\r\n * APIFunction: profile\r\n * Turns on the JavaScript profiler. The optional argument title would\r\n * contain the text to be printed in the header of the profile report.\r\n *\r\n * This function is not currently implemented in Firebug Lite.\r\n * \r\n * Parameters:\r\n * title - {String} Optional title for the profiler\r\n */\r\n profile: function() {},\r\n\r\n /**\r\n * APIFunction: profileEnd\r\n * Turns off the JavaScript profiler and prints its report.\r\n * \r\n * This function is not currently implemented in Firebug Lite.\r\n */\r\n profileEnd: function() {},\r\n\r\n /**\r\n * APIFunction: count\r\n * Writes the number of times that the line of code where count was called\r\n * was executed. The optional argument title will print a message in\r\n * addition to the number of the count.\r\n *\r\n * This function is not currently implemented in Firebug Lite.\r\n *\r\n * Parameters:\r\n * title - {String} Optional title to be printed with count\r\n */\r\n count: function() {},\r\n\r\n CLASS_NAME: \"OpenLayers.Console\"\r\n};\r\n\r\n/**\r\n * Execute an anonymous function to extend the OpenLayers.Console namespace\r\n * if the firebug.js script is included. This closure is used so that the\r\n * \"scripts\" and \"i\" variables don't pollute the global namespace.\r\n */\r\n(function() {\r\n /**\r\n * If Firebug Lite is included (before this script), re-route all\r\n * OpenLayers.Console calls to the console object.\r\n */\r\n var scripts = document.getElementsByTagName(\"script\");\r\n for(var i=0, len=scripts.length; i method to set this value and the method to\r\n * retrieve it.\r\n */\r\n code: null,\r\n\r\n /** \r\n * APIProperty: defaultCode\r\n * {String} Default language to use when a specific language can't be\r\n * found. Default is \"en\".\r\n */\r\n defaultCode: \"en\",\r\n \r\n /**\r\n * APIFunction: getCode\r\n * Get the current language code.\r\n *\r\n * Returns:\r\n * {String} The current language code.\r\n */\r\n getCode: function() {\r\n if(!OpenLayers.Lang.code) {\r\n OpenLayers.Lang.setCode();\r\n }\r\n return OpenLayers.Lang.code;\r\n },\r\n \r\n /**\r\n * APIFunction: setCode\r\n * Set the language code for string translation. This code is used by\r\n * the method.\r\n *\r\n * Parameters:\r\n * code - {String} These codes follow the IETF recommendations at\r\n * http://www.ietf.org/rfc/rfc3066.txt. If no value is set, the\r\n * browser's language setting will be tested. If no \r\n * dictionary exists for the code, the \r\n * will be used.\r\n */\r\n setCode: function(code) {\r\n var lang;\r\n if(!code) {\r\n code = (OpenLayers.BROWSER_NAME == \"msie\") ?\r\n navigator.userLanguage : navigator.language;\r\n }\r\n var parts = code.split('-');\r\n parts[0] = parts[0].toLowerCase();\r\n if(typeof OpenLayers.Lang[parts[0]] == \"object\") {\r\n lang = parts[0];\r\n }\r\n\r\n // check for regional extensions\r\n if(parts[1]) {\r\n var testLang = parts[0] + '-' + parts[1].toUpperCase();\r\n if(typeof OpenLayers.Lang[testLang] == \"object\") {\r\n lang = testLang;\r\n }\r\n }\r\n if(!lang) {\r\n OpenLayers.Console.warn(\r\n 'Failed to find OpenLayers.Lang.' + parts.join(\"-\") +\r\n ' dictionary, falling back to default language'\r\n );\r\n lang = OpenLayers.Lang.defaultCode;\r\n }\r\n \r\n OpenLayers.Lang.code = lang;\r\n },\r\n\r\n /**\r\n * APIMethod: translate\r\n * Looks up a key from a dictionary based on the current language string.\r\n * The value of will be used to determine the appropriate\r\n * dictionary. Dictionaries are stored in .\r\n *\r\n * Parameters:\r\n * key - {String} The key for an i18n string value in the dictionary.\r\n * context - {Object} Optional context to be used with\r\n * .\r\n * \r\n * Returns:\r\n * {String} A internationalized string.\r\n */\r\n translate: function(key, context) {\r\n var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()];\r\n var message = dictionary && dictionary[key];\r\n if(!message) {\r\n // Message not found, fall back to message key\r\n message = key;\r\n }\r\n if(context) {\r\n message = OpenLayers.String.format(message, context);\r\n }\r\n return message;\r\n }\r\n \r\n};\r\n\r\n\r\n/**\r\n * APIMethod: OpenLayers.i18n\r\n * Alias for . Looks up a key from a dictionary\r\n * based on the current language string. The value of\r\n * will be used to determine the appropriate\r\n * dictionary. Dictionaries are stored in .\r\n *\r\n * Parameters:\r\n * key - {String} The key for an i18n string value in the dictionary.\r\n * context - {Object} Optional context to be used with\r\n * .\r\n * \r\n * Returns:\r\n * {String} A internationalized string.\r\n */\r\nOpenLayers.i18n = OpenLayers.Lang.translate;\r\n/* ======================================================================\r\n OpenLayers/Util.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes.js\r\n * @requires OpenLayers/BaseTypes/Bounds.js\r\n * @requires OpenLayers/BaseTypes/Element.js\r\n * @requires OpenLayers/BaseTypes/LonLat.js\r\n * @requires OpenLayers/BaseTypes/Pixel.js\r\n * @requires OpenLayers/BaseTypes/Size.js\r\n * @requires OpenLayers/Lang.js\r\n */\r\n\r\n/**\r\n * Namespace: Util\r\n */\r\nOpenLayers.Util = OpenLayers.Util || {};\r\n\r\n/** \r\n * Function: getElement\r\n * This is the old $() from prototype\r\n *\r\n * Parameters:\r\n * e - {String or DOMElement or Window}\r\n *\r\n * Returns:\r\n * {Array(DOMElement) or DOMElement}\r\n */\r\nOpenLayers.Util.getElement = function() {\r\n var elements = [];\r\n\r\n for (var i=0, len=arguments.length; i= 0; i--) {\r\n if(array[i] == item) {\r\n array.splice(i,1);\r\n //break;more than once??\r\n }\r\n }\r\n return array;\r\n};\r\n\r\n/** \r\n * Function: indexOf\r\n * Seems to exist already in FF, but not in MOZ.\r\n * \r\n * Parameters:\r\n * array - {Array}\r\n * obj - {*}\r\n * \r\n * Returns:\r\n * {Integer} The index at which the first object was found in the array.\r\n * If not found, returns -1.\r\n */\r\nOpenLayers.Util.indexOf = function(array, obj) {\r\n // use the build-in function if available.\r\n if (typeof array.indexOf == \"function\") {\r\n return array.indexOf(obj);\r\n } else {\r\n for (var i = 0, len = array.length; i < len; i++) {\r\n if (array[i] == obj) {\r\n return i;\r\n }\r\n }\r\n return -1; \r\n }\r\n};\r\n\r\n\r\n/**\r\n * Property: dotless\r\n * {RegExp}\r\n * Compiled regular expression to match dots (\".\"). This is used for replacing\r\n * dots in identifiers. Because object identifiers are frequently used for\r\n * DOM element identifiers by the library, we avoid using dots to make for\r\n * more sensible CSS selectors.\r\n *\r\n * TODO: Use a module pattern to avoid bloating the API with stuff like this.\r\n */\r\nOpenLayers.Util.dotless = /\\./g;\r\n\r\n/**\r\n * Function: modifyDOMElement\r\n * \r\n * Modifies many properties of a DOM element all at once. Passing in \r\n * null to an individual parameter will avoid setting the attribute.\r\n *\r\n * Parameters:\r\n * element - {DOMElement} DOM element to modify.\r\n * id - {String} The element id attribute to set. Note that dots (\".\") will be\r\n * replaced with underscore (\"_\") in setting the element id.\r\n * px - {|Object} The element left and top position,\r\n * OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * sz - {|Object} The element width and height,\r\n * OpenLayers.Size or an object with a\r\n * 'w' and 'h' properties.\r\n * position - {String} The position attribute. eg: absolute, \r\n * relative, etc.\r\n * border - {String} The style.border attribute. eg:\r\n * solid black 2px\r\n * overflow - {String} The style.overview attribute. \r\n * opacity - {Float} Fractional value (0.0 - 1.0)\r\n */\r\nOpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, \r\n border, overflow, opacity) {\r\n\r\n if (id) {\r\n element.id = id.replace(OpenLayers.Util.dotless, \"_\");\r\n }\r\n if (px) {\r\n element.style.left = px.x + \"px\";\r\n element.style.top = px.y + \"px\";\r\n }\r\n if (sz) {\r\n element.style.width = sz.w + \"px\";\r\n element.style.height = sz.h + \"px\";\r\n }\r\n if (position) {\r\n element.style.position = position;\r\n }\r\n if (border) {\r\n element.style.border = border;\r\n }\r\n if (overflow) {\r\n element.style.overflow = overflow;\r\n }\r\n if (parseFloat(opacity) >= 0.0 && parseFloat(opacity) < 1.0) {\r\n element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';\r\n element.style.opacity = opacity;\r\n } else if (parseFloat(opacity) == 1.0) {\r\n element.style.filter = '';\r\n element.style.opacity = '';\r\n }\r\n};\r\n\r\n/** \r\n * Function: createDiv\r\n * Creates a new div and optionally set some standard attributes.\r\n * Null may be passed to each parameter if you do not wish to\r\n * set a particular attribute.\r\n * Note - zIndex is NOT set on the resulting div.\r\n * \r\n * Parameters:\r\n * id - {String} An identifier for this element. If no id is\r\n * passed an identifier will be created \r\n * automatically. Note that dots (\".\") will be replaced with\r\n * underscore (\"_\") when generating ids.\r\n * px - {|Object} The element left and top position,\r\n * OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * sz - {|Object} The element width and height,\r\n * OpenLayers.Size or an object with a\r\n * 'w' and 'h' properties.\r\n * imgURL - {String} A url pointing to an image to use as a \r\n * background image.\r\n * position - {String} The style.position value. eg: absolute,\r\n * relative etc.\r\n * border - {String} The the style.border value. \r\n * eg: 2px solid black\r\n * overflow - {String} The style.overflow value. Eg. hidden\r\n * opacity - {Float} Fractional value (0.0 - 1.0)\r\n * \r\n * Returns: \r\n * {DOMElement} A DOM Div created with the specified attributes.\r\n */\r\nOpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, \r\n border, overflow, opacity) {\r\n\r\n var dom = document.createElement('div');\r\n\r\n if (imgURL) {\r\n dom.style.backgroundImage = 'url(' + imgURL + ')';\r\n }\r\n\r\n //set generic properties\r\n if (!id) {\r\n id = OpenLayers.Util.createUniqueID(\"OpenLayersDiv\");\r\n }\r\n if (!position) {\r\n position = \"absolute\";\r\n }\r\n OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, \r\n border, overflow, opacity);\r\n\r\n return dom;\r\n};\r\n\r\n/**\r\n * Function: createImage\r\n * Creates an img element with specific attribute values.\r\n * \r\n * Parameters:\r\n * id - {String} The id field for the img. If none assigned one will be\r\n * automatically generated.\r\n * px - {|Object} The element left and top position,\r\n * OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * sz - {|Object} The element width and height,\r\n * OpenLayers.Size or an object with a\r\n * 'w' and 'h' properties.\r\n * imgURL - {String} The url to use as the image source.\r\n * position - {String} The style.position value.\r\n * border - {String} The border to place around the image.\r\n * opacity - {Float} Fractional value (0.0 - 1.0)\r\n * delayDisplay - {Boolean} If true waits until the image has been\r\n * loaded.\r\n * \r\n * Returns:\r\n * {DOMElement} A DOM Image created with the specified attributes.\r\n */\r\nOpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border,\r\n opacity, delayDisplay) {\r\n\r\n var image = document.createElement(\"img\");\r\n\r\n //set generic properties\r\n if (!id) {\r\n id = OpenLayers.Util.createUniqueID(\"OpenLayersDiv\");\r\n }\r\n if (!position) {\r\n position = \"relative\";\r\n }\r\n OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, \r\n border, null, opacity);\r\n\r\n if (delayDisplay) {\r\n image.style.display = \"none\";\r\n function display() {\r\n image.style.display = \"\";\r\n OpenLayers.Event.stopObservingElement(image);\r\n }\r\n OpenLayers.Event.observe(image, \"load\", display);\r\n OpenLayers.Event.observe(image, \"error\", display);\r\n }\r\n \r\n //set special properties\r\n image.style.alt = id;\r\n image.galleryImg = \"no\";\r\n if (imgURL) {\r\n image.src = imgURL;\r\n }\r\n \r\n return image;\r\n};\r\n\r\n/**\r\n * Property: IMAGE_RELOAD_ATTEMPTS\r\n * {Integer} How many times should we try to reload an image before giving up?\r\n * Default is 0\r\n */\r\nOpenLayers.IMAGE_RELOAD_ATTEMPTS = 0;\r\n\r\n/**\r\n * Property: alphaHackNeeded\r\n * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.\r\n */\r\nOpenLayers.Util.alphaHackNeeded = null;\r\n\r\n/**\r\n * Function: alphaHack\r\n * Checks whether it's necessary (and possible) to use the png alpha\r\n * hack which allows alpha transparency for png images under Internet\r\n * Explorer.\r\n * \r\n * Returns:\r\n * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.\r\n */\r\nOpenLayers.Util.alphaHack = function() {\r\n if (OpenLayers.Util.alphaHackNeeded == null) {\r\n var arVersion = navigator.appVersion.split(\"MSIE\");\r\n var version = parseFloat(arVersion[1]);\r\n var filter = false;\r\n \r\n // IEs4Lin dies when trying to access document.body.filters, because \r\n // the property is there, but requires a DLL that can't be provided. This\r\n // means that we need to wrap this in a try/catch so that this can\r\n // continue.\r\n \r\n try { \r\n filter = !!(document.body.filters);\r\n } catch (e) {} \r\n \r\n OpenLayers.Util.alphaHackNeeded = (filter && \r\n (version >= 5.5) && (version < 7));\r\n }\r\n return OpenLayers.Util.alphaHackNeeded;\r\n};\r\n\r\n/** \r\n * Function: modifyAlphaImageDiv\r\n * \r\n * Parameters:\r\n * div - {DOMElement} Div containing Alpha-adjusted Image\r\n * id - {String}\r\n * px - {|Object} OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * sz - {|Object} OpenLayers.Size or an object with\r\n * a 'w' and 'h' properties.\r\n * imgURL - {String}\r\n * position - {String}\r\n * border - {String}\r\n * sizing - {String} 'crop', 'scale', or 'image'. Default is \"scale\"\r\n * opacity - {Float} Fractional value (0.0 - 1.0)\r\n */ \r\nOpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, \r\n position, border, sizing, \r\n opacity) {\r\n\r\n OpenLayers.Util.modifyDOMElement(div, id, px, sz, position,\r\n null, null, opacity);\r\n\r\n var img = div.childNodes[0];\r\n\r\n if (imgURL) {\r\n img.src = imgURL;\r\n }\r\n OpenLayers.Util.modifyDOMElement(img, div.id + \"_innerImage\", null, sz, \r\n \"relative\", border);\r\n \r\n if (OpenLayers.Util.alphaHack()) {\r\n if(div.style.display != \"none\") {\r\n div.style.display = \"inline-block\";\r\n }\r\n if (sizing == null) {\r\n sizing = \"scale\";\r\n }\r\n \r\n div.style.filter = \"progid:DXImageTransform.Microsoft\" +\r\n \".AlphaImageLoader(src='\" + img.src + \"', \" +\r\n \"sizingMethod='\" + sizing + \"')\";\r\n if (parseFloat(div.style.opacity) >= 0.0 && \r\n parseFloat(div.style.opacity) < 1.0) {\r\n div.style.filter += \" alpha(opacity=\" + div.style.opacity * 100 + \")\";\r\n }\r\n\r\n img.style.filter = \"alpha(opacity=0)\";\r\n }\r\n};\r\n\r\n/** \r\n * Function: createAlphaImageDiv\r\n * \r\n * Parameters:\r\n * id - {String}\r\n * px - {|Object} OpenLayers.Pixel or an object with\r\n * a 'x' and 'y' properties.\r\n * sz - {|Object} OpenLayers.Size or an object with\r\n * a 'w' and 'h' properties.\r\n * imgURL - {String}\r\n * position - {String}\r\n * border - {String}\r\n * sizing - {String} 'crop', 'scale', or 'image'. Default is \"scale\"\r\n * opacity - {Float} Fractional value (0.0 - 1.0)\r\n * delayDisplay - {Boolean} If true waits until the image has been\r\n * loaded.\r\n * \r\n * Returns:\r\n * {DOMElement} A DOM Div created with a DOM Image inside it. If the hack is \r\n * needed for transparency in IE, it is added.\r\n */ \r\nOpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, \r\n position, border, sizing, \r\n opacity, delayDisplay) {\r\n \r\n var div = OpenLayers.Util.createDiv();\r\n var img = OpenLayers.Util.createImage(null, null, null, null, null, null, \r\n null, delayDisplay);\r\n img.className = \"olAlphaImg\";\r\n div.appendChild(img);\r\n\r\n OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, \r\n border, sizing, opacity);\r\n \r\n return div;\r\n};\r\n\r\n\r\n/** \r\n * Function: upperCaseObject\r\n * Creates a new hashtable and copies over all the keys from the \r\n * passed-in object, but storing them under an uppercased\r\n * version of the key at which they were stored.\r\n * \r\n * Parameters: \r\n * object - {Object}\r\n * \r\n * Returns: \r\n * {Object} A new Object with all the same keys but uppercased\r\n */\r\nOpenLayers.Util.upperCaseObject = function (object) {\r\n var uObject = {};\r\n for (var key in object) {\r\n uObject[key.toUpperCase()] = object[key];\r\n }\r\n return uObject;\r\n};\r\n\r\n/** \r\n * Function: applyDefaults\r\n * Takes an object and copies any properties that don't exist from\r\n * another properties, by analogy with OpenLayers.Util.extend() from\r\n * Prototype.js.\r\n * \r\n * Parameters:\r\n * to - {Object} The destination object.\r\n * from - {Object} The source object. Any properties of this object that\r\n * are undefined in the to object will be set on the to object.\r\n *\r\n * Returns:\r\n * {Object} A reference to the to object. Note that the to argument is modified\r\n * in place and returned by this function.\r\n */\r\nOpenLayers.Util.applyDefaults = function (to, from) {\r\n to = to || {};\r\n /*\r\n * FF/Windows < 2.0.0.13 reports \"Illegal operation on WrappedNative\r\n * prototype object\" when calling hawOwnProperty if the source object is an\r\n * instance of window.Event.\r\n */\r\n var fromIsEvt = typeof window.Event == \"function\"\r\n && from instanceof window.Event;\r\n\r\n for (var key in from) {\r\n if (to[key] === undefined ||\r\n (!fromIsEvt && from.hasOwnProperty\r\n && from.hasOwnProperty(key) && !to.hasOwnProperty(key))) {\r\n to[key] = from[key];\r\n }\r\n }\r\n /**\r\n * IE doesn't include the toString property when iterating over an object's\r\n * properties with the for(property in object) syntax. Explicitly check if\r\n * the source has its own toString property.\r\n */\r\n if(!fromIsEvt && from && from.hasOwnProperty\r\n && from.hasOwnProperty('toString') && !to.hasOwnProperty('toString')) {\r\n to.toString = from.toString;\r\n }\r\n \r\n return to;\r\n};\r\n\r\n/**\r\n * Function: getParameterString\r\n * \r\n * Parameters:\r\n * params - {Object}\r\n * \r\n * Returns:\r\n * {String} A concatenation of the properties of an object in \r\n * http parameter notation. \r\n * (ex. \"key1=value1&key2=value2&key3=value3\")\r\n * If a parameter is actually a list, that parameter will then\r\n * be set to a comma-seperated list of values (foo,bar) instead\r\n * of being URL escaped (foo%3Abar). \r\n */\r\nOpenLayers.Util.getParameterString = function(params) {\r\n var paramsArray = [];\r\n \r\n for (var key in params) {\r\n var value = params[key];\r\n if ((value != null) && (typeof value != 'function')) {\r\n var encodedValue;\r\n if (typeof value == 'object' && value.constructor == Array) {\r\n /* value is an array; encode items and separate with \",\" */\r\n var encodedItemArray = [];\r\n var item;\r\n for (var itemIndex=0, len=value.length; itemIndex} (or any object with both .lat, .lon properties)\r\n * p2 - {} (or any object with both .lat, .lon properties)\r\n *\r\n * Returns:\r\n * {Float} The distance (in km) between the two input points as measured on an\r\n * ellipsoid. Note that the input point objects must be in geographic\r\n * coordinates (decimal degrees) and the return distance is in kilometers.\r\n */\r\nOpenLayers.Util.distVincenty = function(p1, p2) {\r\n var ct = OpenLayers.Util.VincentyConstants;\r\n var a = ct.a, b = ct.b, f = ct.f;\r\n\r\n var L = OpenLayers.Util.rad(p2.lon - p1.lon);\r\n var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));\r\n var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));\r\n var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);\r\n var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);\r\n var lambda = L, lambdaP = 2*Math.PI;\r\n var iterLimit = 20;\r\n while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {\r\n var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);\r\n var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +\r\n (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));\r\n if (sinSigma==0) {\r\n return 0; // co-incident points\r\n }\r\n var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;\r\n var sigma = Math.atan2(sinSigma, cosSigma);\r\n var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);\r\n var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);\r\n var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;\r\n var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));\r\n lambdaP = lambda;\r\n lambda = L + (1-C) * f * Math.sin(alpha) *\r\n (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));\r\n }\r\n if (iterLimit==0) {\r\n return NaN; // formula failed to converge\r\n }\r\n var uSq = cosSqAlpha * (a*a - b*b) / (b*b);\r\n var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));\r\n var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));\r\n var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-\r\n B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));\r\n var s = b*A*(sigma-deltaSigma);\r\n var d = s.toFixed(3)/1000; // round to 1mm precision\r\n return d;\r\n};\r\n\r\n/**\r\n * APIFunction: destinationVincenty\r\n * Calculate destination point given start point lat/long (numeric degrees),\r\n * bearing (numeric degrees) & distance (in m).\r\n * Adapted from Chris Veness work, see\r\n * http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html\r\n *\r\n * Parameters:\r\n * lonlat - {} (or any object with both .lat, .lon\r\n * properties) The start point.\r\n * brng - {Float} The bearing (degrees).\r\n * dist - {Float} The ground distance (meters).\r\n *\r\n * Returns:\r\n * {} The destination point.\r\n */\r\nOpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {\r\n var u = OpenLayers.Util;\r\n var ct = u.VincentyConstants;\r\n var a = ct.a, b = ct.b, f = ct.f;\r\n\r\n var lon1 = lonlat.lon;\r\n var lat1 = lonlat.lat;\r\n\r\n var s = dist;\r\n var alpha1 = u.rad(brng);\r\n var sinAlpha1 = Math.sin(alpha1);\r\n var cosAlpha1 = Math.cos(alpha1);\r\n\r\n var tanU1 = (1-f) * Math.tan(u.rad(lat1));\r\n var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;\r\n var sigma1 = Math.atan2(tanU1, cosAlpha1);\r\n var sinAlpha = cosU1 * sinAlpha1;\r\n var cosSqAlpha = 1 - sinAlpha*sinAlpha;\r\n var uSq = cosSqAlpha * (a*a - b*b) / (b*b);\r\n var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));\r\n var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));\r\n\r\n var sigma = s / (b*A), sigmaP = 2*Math.PI;\r\n while (Math.abs(sigma-sigmaP) > 1e-12) {\r\n var cos2SigmaM = Math.cos(2*sigma1 + sigma);\r\n var sinSigma = Math.sin(sigma);\r\n var cosSigma = Math.cos(sigma);\r\n var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-\r\n B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));\r\n sigmaP = sigma;\r\n sigma = s / (b*A) + deltaSigma;\r\n }\r\n\r\n var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;\r\n var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,\r\n (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));\r\n var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);\r\n var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));\r\n var L = lambda - (1-C) * f * sinAlpha *\r\n (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));\r\n\r\n var revAz = Math.atan2(sinAlpha, -tmp); // final bearing\r\n\r\n return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));\r\n};\r\n\r\n/**\r\n * Function: getParameters\r\n * Parse the parameters from a URL or from the current page itself into a \r\n * JavaScript Object. Note that parameter values with commas are separated\r\n * out into an Array.\r\n * \r\n * Parameters:\r\n * url - {String} Optional url used to extract the query string.\r\n * If url is null or is not supplied, query string is taken \r\n * from the page location.\r\n * options - {Object} Additional options. Optional.\r\n *\r\n * Valid options:\r\n * splitArgs - {Boolean} Split comma delimited params into arrays? Default is\r\n * true.\r\n * \r\n * Returns:\r\n * {Object} An object of key/value pairs from the query string.\r\n */\r\nOpenLayers.Util.getParameters = function(url, options) {\r\n options = options || {};\r\n // if no url specified, take it from the location bar\r\n url = (url === null || url === undefined) ? window.location.href : url;\r\n\r\n //parse out parameters portion of url string\r\n var paramsString = \"\";\r\n if (OpenLayers.String.contains(url, '?')) {\r\n var start = url.indexOf('?') + 1;\r\n var end = OpenLayers.String.contains(url, \"#\") ?\r\n url.indexOf('#') : url.length;\r\n paramsString = url.substring(start, end);\r\n }\r\n\r\n var parameters = {};\r\n var pairs = paramsString.split(/[&;]/);\r\n for(var i=0, len=pairs.length; i 1.0) ? (1.0 / scale) \r\n : scale;\r\n return normScale;\r\n};\r\n\r\n/**\r\n * Function: getResolutionFromScale\r\n * \r\n * Parameters:\r\n * scale - {Float}\r\n * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.\r\n * Default is degrees\r\n * \r\n * Returns:\r\n * {Float} The corresponding resolution given passed-in scale and unit \r\n * parameters. If the given scale is falsey, the returned resolution will\r\n * be undefined.\r\n */\r\nOpenLayers.Util.getResolutionFromScale = function (scale, units) {\r\n var resolution;\r\n if (scale) {\r\n if (units == null) {\r\n units = \"degrees\";\r\n }\r\n var normScale = OpenLayers.Util.normalizeScale(scale);\r\n resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]\r\n * OpenLayers.DOTS_PER_INCH); \r\n }\r\n return resolution;\r\n};\r\n\r\n/**\r\n * Function: getScaleFromResolution\r\n * \r\n * Parameters:\r\n * resolution - {Float}\r\n * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.\r\n * Default is degrees\r\n * \r\n * Returns:\r\n * {Float} The corresponding scale given passed-in resolution and unit \r\n * parameters.\r\n */\r\nOpenLayers.Util.getScaleFromResolution = function (resolution, units) {\r\n\r\n if (units == null) {\r\n units = \"degrees\";\r\n }\r\n\r\n var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] *\r\n OpenLayers.DOTS_PER_INCH;\r\n return scale;\r\n};\r\n\r\n/**\r\n * Function: pagePosition\r\n * Calculates the position of an element on the page (see\r\n * http://code.google.com/p/doctype/wiki/ArticlePageOffset)\r\n *\r\n * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is\r\n * Copyright (c) 2006, Yahoo! Inc.\r\n * All rights reserved.\r\n * \r\n * Redistribution and use of this software in source and binary forms, with or\r\n * without modification, are permitted provided that the following conditions\r\n * are met:\r\n * \r\n * * Redistributions of source code must retain the above copyright notice,\r\n * this list of conditions and the following disclaimer.\r\n * \r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n * this list of conditions and the following disclaimer in the documentation\r\n * and/or other materials provided with the distribution.\r\n * \r\n * * Neither the name of Yahoo! Inc. nor the names of its contributors may be\r\n * used to endorse or promote products derived from this software without\r\n * specific prior written permission of Yahoo! Inc.\r\n * \r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\r\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \r\n * POSSIBILITY OF SUCH DAMAGE.\r\n *\r\n * Parameters:\r\n * forElement - {DOMElement}\r\n * \r\n * Returns:\r\n * {Array} two item array, Left value then Top value.\r\n */\r\nOpenLayers.Util.pagePosition = function(forElement) {\r\n // NOTE: If element is hidden (display none or disconnected or any the\r\n // ancestors are hidden) we get (0,0) by default but we still do the\r\n // accumulation of scroll position.\r\n\r\n var pos = [0, 0];\r\n var viewportElement = OpenLayers.Util.getViewportElement();\r\n if (!forElement || forElement == window || forElement == viewportElement) {\r\n // viewport is always at 0,0 as that defined the coordinate system for\r\n // this function - this avoids special case checks in the code below\r\n return pos;\r\n }\r\n\r\n // Gecko browsers normally use getBoxObjectFor to calculate the position.\r\n // When invoked for an element with an implicit absolute position though it\r\n // can be off by one. Therefore the recursive implementation is used in\r\n // those (relatively rare) cases.\r\n var BUGGY_GECKO_BOX_OBJECT =\r\n OpenLayers.IS_GECKO && document.getBoxObjectFor &&\r\n OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' &&\r\n (forElement.style.top == '' || forElement.style.left == '');\r\n\r\n var parent = null;\r\n var box;\r\n\r\n if (forElement.getBoundingClientRect) { // IE\r\n box = forElement.getBoundingClientRect();\r\n var scrollTop = window.pageYOffset || viewportElement.scrollTop;\r\n var scrollLeft = window.pageXOffset || viewportElement.scrollLeft;\r\n \r\n pos[0] = box.left + scrollLeft;\r\n pos[1] = box.top + scrollTop;\r\n\r\n } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko\r\n // Gecko ignores the scroll values for ancestors, up to 1.9. See:\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=330619\r\n\r\n box = document.getBoxObjectFor(forElement);\r\n var vpBox = document.getBoxObjectFor(viewportElement);\r\n pos[0] = box.screenX - vpBox.screenX;\r\n pos[1] = box.screenY - vpBox.screenY;\r\n\r\n } else { // safari/opera\r\n pos[0] = forElement.offsetLeft;\r\n pos[1] = forElement.offsetTop;\r\n parent = forElement.offsetParent;\r\n if (parent != forElement) {\r\n while (parent) {\r\n pos[0] += parent.offsetLeft;\r\n pos[1] += parent.offsetTop;\r\n parent = parent.offsetParent;\r\n }\r\n }\r\n\r\n var browser = OpenLayers.BROWSER_NAME;\r\n\r\n // opera & (safari absolute) incorrectly account for body offsetTop\r\n if (browser == \"opera\" || (browser == \"safari\" &&\r\n OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) {\r\n pos[1] -= document.body.offsetTop;\r\n }\r\n\r\n // accumulate the scroll positions for everything but the body element\r\n parent = forElement.offsetParent;\r\n while (parent && parent != document.body) {\r\n pos[0] -= parent.scrollLeft;\r\n // see https://bugs.opera.com/show_bug.cgi?id=249965\r\n if (browser != \"opera\" || parent.tagName != 'TR') {\r\n pos[1] -= parent.scrollTop;\r\n }\r\n parent = parent.offsetParent;\r\n }\r\n }\r\n \r\n return pos;\r\n};\r\n\r\n/**\r\n * Function: getViewportElement\r\n * Returns die viewport element of the document. The viewport element is\r\n * usually document.documentElement, except in IE,where it is either\r\n * document.body or document.documentElement, depending on the document's\r\n * compatibility mode (see\r\n * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement)\r\n *\r\n * Returns:\r\n * {DOMElement}\r\n */\r\nOpenLayers.Util.getViewportElement = function() {\r\n var viewportElement = arguments.callee.viewportElement;\r\n if (viewportElement == undefined) {\r\n viewportElement = (OpenLayers.BROWSER_NAME == \"msie\" &&\r\n document.compatMode != 'CSS1Compat') ? document.body :\r\n document.documentElement;\r\n arguments.callee.viewportElement = viewportElement;\r\n }\r\n return viewportElement;\r\n};\r\n\r\n/** \r\n * Function: isEquivalentUrl\r\n * Test two URLs for equivalence. \r\n * \r\n * Setting 'ignoreCase' allows for case-independent comparison.\r\n * \r\n * Comparison is based on: \r\n * - Protocol\r\n * - Host (evaluated without the port)\r\n * - Port (set 'ignorePort80' to ignore \"80\" values)\r\n * - Hash ( set 'ignoreHash' to disable)\r\n * - Pathname (for relative <-> absolute comparison) \r\n * - Arguments (so they can be out of order)\r\n * \r\n * Parameters:\r\n * url1 - {String}\r\n * url2 - {String}\r\n * options - {Object} Allows for customization of comparison:\r\n * 'ignoreCase' - Default is True\r\n * 'ignorePort80' - Default is True\r\n * 'ignoreHash' - Default is True\r\n *\r\n * Returns:\r\n * {Boolean} Whether or not the two URLs are equivalent\r\n */\r\nOpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {\r\n options = options || {};\r\n\r\n OpenLayers.Util.applyDefaults(options, {\r\n ignoreCase: true,\r\n ignorePort80: true,\r\n ignoreHash: true,\r\n splitArgs: false\r\n });\r\n\r\n var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);\r\n var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);\r\n\r\n //compare all keys except for \"args\" (treated below)\r\n for(var key in urlObj1) {\r\n if(key !== \"args\") {\r\n if(urlObj1[key] != urlObj2[key]) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n // compare search args - irrespective of order\r\n for(var key in urlObj1.args) {\r\n if(urlObj1.args[key] != urlObj2.args[key]) {\r\n return false;\r\n }\r\n delete urlObj2.args[key];\r\n }\r\n // urlObj2 shouldn't have any args left\r\n for(var key in urlObj2.args) {\r\n return false;\r\n }\r\n \r\n return true;\r\n};\r\n\r\n/**\r\n * Function: createUrlObject\r\n * \r\n * Parameters:\r\n * url - {String}\r\n * options - {Object} A hash of options.\r\n *\r\n * Valid options:\r\n * ignoreCase - {Boolean} lowercase url,\r\n * ignorePort80 - {Boolean} don't include explicit port if port is 80,\r\n * ignoreHash - {Boolean} Don't include part of url after the hash (#).\r\n * splitArgs - {Boolean} Split comma delimited params into arrays? Default is\r\n * true.\r\n * \r\n * Returns:\r\n * {Object} An object with separate url, a, port, host, and args parsed out \r\n * and ready for comparison\r\n */\r\nOpenLayers.Util.createUrlObject = function(url, options) {\r\n options = options || {};\r\n\r\n // deal with relative urls first\r\n if(!(/^\\w+:\\/\\//).test(url)) {\r\n var loc = window.location;\r\n var port = loc.port ? \":\" + loc.port : \"\";\r\n var fullUrl = loc.protocol + \"//\" + loc.host.split(\":\").shift() + port;\r\n if(url.indexOf(\"/\") === 0) {\r\n // full pathname\r\n url = fullUrl + url;\r\n } else {\r\n // relative to current path\r\n var parts = loc.pathname.split(\"/\");\r\n parts.pop();\r\n url = fullUrl + parts.join(\"/\") + \"/\" + url;\r\n }\r\n }\r\n \r\n if (options.ignoreCase) {\r\n url = url.toLowerCase(); \r\n }\r\n\r\n var a = document.createElement('a');\r\n a.href = url;\r\n \r\n var urlObject = {};\r\n \r\n //host (without port)\r\n urlObject.host = a.host.split(\":\").shift();\r\n\r\n //protocol\r\n urlObject.protocol = a.protocol; \r\n\r\n //port (get uniform browser behavior with port 80 here)\r\n if(options.ignorePort80) {\r\n urlObject.port = (a.port == \"80\" || a.port == \"0\") ? \"\" : a.port;\r\n } else {\r\n urlObject.port = (a.port == \"\" || a.port == \"0\") ? \"80\" : a.port;\r\n }\r\n\r\n //hash\r\n urlObject.hash = (options.ignoreHash || a.hash === \"#\") ? \"\" : a.hash; \r\n \r\n //args\r\n var queryString = a.search;\r\n if (!queryString) {\r\n var qMark = url.indexOf(\"?\");\r\n queryString = (qMark != -1) ? url.substr(qMark) : \"\";\r\n }\r\n urlObject.args = OpenLayers.Util.getParameters(queryString,\r\n {splitArgs: options.splitArgs});\r\n\r\n // pathname\r\n //\r\n // This is a workaround for Internet Explorer where\r\n // window.location.pathname has a leading \"/\", but\r\n // a.pathname has no leading \"/\".\r\n urlObject.pathname = (a.pathname.charAt(0) == \"/\") ? a.pathname : \"/\" + a.pathname;\r\n \r\n return urlObject; \r\n};\r\n \r\n/**\r\n * Function: removeTail\r\n * Takes a url and removes everything after the ? and #\r\n * \r\n * Parameters:\r\n * url - {String} The url to process\r\n * \r\n * Returns:\r\n * {String} The string with all queryString and Hash removed\r\n */\r\nOpenLayers.Util.removeTail = function(url) {\r\n var head = null;\r\n \r\n var qMark = url.indexOf(\"?\");\r\n var hashMark = url.indexOf(\"#\");\r\n\r\n if (qMark == -1) {\r\n head = (hashMark != -1) ? url.substr(0,hashMark) : url;\r\n } else {\r\n head = (hashMark != -1) ? url.substr(0,Math.min(qMark, hashMark)) \r\n : url.substr(0, qMark);\r\n }\r\n return head;\r\n};\r\n\r\n/**\r\n * Constant: IS_GECKO\r\n * {Boolean} True if the userAgent reports the browser to use the Gecko engine\r\n */\r\nOpenLayers.IS_GECKO = (function() {\r\n var ua = navigator.userAgent.toLowerCase();\r\n return ua.indexOf(\"webkit\") == -1 && ua.indexOf(\"gecko\") != -1;\r\n})();\r\n\r\n/**\r\n * Constant: CANVAS_SUPPORTED\r\n * {Boolean} True if canvas 2d is supported.\r\n */\r\nOpenLayers.CANVAS_SUPPORTED = (function() {\r\n var elem = document.createElement('canvas');\r\n return !!(elem.getContext && elem.getContext('2d'));\r\n})();\r\n\r\n/**\r\n * Constant: BROWSER_NAME\r\n * {String}\r\n * A substring of the navigator.userAgent property. Depending on the userAgent\r\n * property, this will be the empty string or one of the following:\r\n * * \"opera\" -- Opera\r\n * * \"msie\" -- Internet Explorer\r\n * * \"safari\" -- Safari\r\n * * \"firefox\" -- Firefox\r\n * * \"mozilla\" -- Mozilla\r\n */\r\nOpenLayers.BROWSER_NAME = (function() {\r\n var name = \"\";\r\n var ua = navigator.userAgent.toLowerCase();\r\n if (ua.indexOf(\"opera\") != -1) {\r\n name = \"opera\";\r\n } else if (ua.indexOf(\"msie\") != -1) {\r\n name = \"msie\";\r\n } else if (ua.indexOf(\"safari\") != -1) {\r\n name = \"safari\";\r\n } else if (ua.indexOf(\"mozilla\") != -1) {\r\n if (ua.indexOf(\"firefox\") != -1) {\r\n name = \"firefox\";\r\n } else {\r\n name = \"mozilla\";\r\n }\r\n }\r\n return name;\r\n})();\r\n\r\n/**\r\n * Function: getBrowserName\r\n * \r\n * Returns:\r\n * {String} A string which specifies which is the current \r\n * browser in which we are running. \r\n * \r\n * Currently-supported browser detection and codes:\r\n * * 'opera' -- Opera\r\n * * 'msie' -- Internet Explorer\r\n * * 'safari' -- Safari\r\n * * 'firefox' -- Firefox\r\n * * 'mozilla' -- Mozilla\r\n * \r\n * If we are unable to property identify the browser, we \r\n * return an empty string.\r\n */\r\nOpenLayers.Util.getBrowserName = function() {\r\n return OpenLayers.BROWSER_NAME;\r\n};\r\n\r\n/**\r\n * Method: getRenderedDimensions\r\n * Renders the contentHTML offscreen to determine actual dimensions for\r\n * popup sizing. As we need layout to determine dimensions the content\r\n * is rendered -9999px to the left and absolute to ensure the \r\n * scrollbars do not flicker\r\n * \r\n * Parameters:\r\n * contentHTML\r\n * size - {} If either the 'w' or 'h' properties is \r\n * specified, we fix that dimension of the div to be measured. This is \r\n * useful in the case where we have a limit in one dimension and must \r\n * therefore meaure the flow in the other dimension.\r\n * options - {Object}\r\n *\r\n * Allowed Options:\r\n * displayClass - {String} Optional parameter. A CSS class name(s) string\r\n * to provide the CSS context of the rendered content.\r\n * containerElement - {DOMElement} Optional parameter. Insert the HTML to \r\n * this node instead of the body root when calculating dimensions. \r\n * \r\n * Returns:\r\n * {}\r\n */\r\nOpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) {\r\n \r\n var w, h;\r\n \r\n // create temp container div with restricted size\r\n var container = document.createElement(\"div\");\r\n container.style.visibility = \"hidden\";\r\n \r\n var containerElement = (options && options.containerElement) \r\n ? options.containerElement : document.body;\r\n \r\n // Opera and IE7 can't handle a node with position:aboslute if it inherits\r\n // position:absolute from a parent.\r\n var parentHasPositionAbsolute = false;\r\n var superContainer = null;\r\n var parent = containerElement;\r\n while (parent && parent.tagName.toLowerCase()!=\"body\") {\r\n var parentPosition = OpenLayers.Element.getStyle(parent, \"position\");\r\n if(parentPosition == \"absolute\") {\r\n parentHasPositionAbsolute = true;\r\n break;\r\n } else if (parentPosition && parentPosition != \"static\") {\r\n break;\r\n }\r\n parent = parent.parentNode;\r\n }\r\n if(parentHasPositionAbsolute && (containerElement.clientHeight === 0 || \r\n containerElement.clientWidth === 0) ){\r\n superContainer = document.createElement(\"div\");\r\n superContainer.style.visibility = \"hidden\";\r\n superContainer.style.position = \"absolute\";\r\n superContainer.style.overflow = \"visible\";\r\n superContainer.style.width = document.body.clientWidth + \"px\";\r\n superContainer.style.height = document.body.clientHeight + \"px\";\r\n superContainer.appendChild(container);\r\n }\r\n container.style.position = \"absolute\";\r\n\r\n //fix a dimension, if specified.\r\n if (size) {\r\n if (size.w) {\r\n w = size.w;\r\n container.style.width = w + \"px\";\r\n } else if (size.h) {\r\n h = size.h;\r\n container.style.height = h + \"px\";\r\n }\r\n }\r\n\r\n //add css classes, if specified\r\n if (options && options.displayClass) {\r\n container.className = options.displayClass;\r\n }\r\n \r\n // create temp content div and assign content\r\n var content = document.createElement(\"div\");\r\n content.innerHTML = contentHTML;\r\n \r\n // we need overflow visible when calculating the size\r\n content.style.overflow = \"visible\";\r\n if (content.childNodes) {\r\n for (var i=0, l=content.childNodes.length; i= 60) { \r\n coordinateseconds -= 60; \r\n coordinateminutes += 1; \r\n if( coordinateminutes >= 60) { \r\n coordinateminutes -= 60; \r\n coordinatedegrees += 1; \r\n } \r\n }\r\n \r\n if( coordinatedegrees < 10 ) {\r\n coordinatedegrees = \"0\" + coordinatedegrees;\r\n }\r\n var str = coordinatedegrees + \"\\u00B0\";\r\n\r\n if (dmsOption.indexOf('dm') >= 0) {\r\n if( coordinateminutes < 10 ) {\r\n coordinateminutes = \"0\" + coordinateminutes;\r\n }\r\n str += coordinateminutes + \"'\";\r\n \r\n if (dmsOption.indexOf('dms') >= 0) {\r\n if( coordinateseconds < 10 ) {\r\n coordinateseconds = \"0\" + coordinateseconds;\r\n }\r\n str += coordinateseconds + '\"';\r\n }\r\n }\r\n \r\n if (axis == \"lon\") {\r\n str += coordinate < 0 ? OpenLayers.i18n(\"W\") : OpenLayers.i18n(\"E\");\r\n } else {\r\n str += coordinate < 0 ? OpenLayers.i18n(\"S\") : OpenLayers.i18n(\"N\");\r\n }\r\n return str;\r\n};\r\n\r\n/**\r\n * Function: getConstructor\r\n * Take an OpenLayers style CLASS_NAME and return a constructor.\r\n *\r\n * Parameters:\r\n * className - {String} The dot delimited class name (e.g. 'OpenLayers.Foo').\r\n * \r\n * Returns:\r\n * {Function} The constructor.\r\n */\r\nOpenLayers.Util.getConstructor = function(className) {\r\n var Constructor;\r\n var parts = className.split('.');\r\n if (parts[0] === \"OpenLayers\") {\r\n Constructor = OpenLayers;\r\n } else {\r\n // someone extended our base class and used their own namespace\r\n // this will not work when the library is evaluated in a closure\r\n // but it is the best we can do (until we ourselves provide a global)\r\n Constructor = window[parts[0]];\r\n }\r\n for (var i = 1, ii = parts.length; i < ii; ++i) {\r\n Constructor = Constructor[parts[i]];\r\n }\r\n return Constructor;\r\n};\r\n/* ======================================================================\r\n OpenLayers/Format.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n * @requires OpenLayers/Util.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Format\r\n * Base class for format reading/writing a variety of formats. Subclasses\r\n * of OpenLayers.Format are expected to have read and write methods.\r\n */\r\nOpenLayers.Format = OpenLayers.Class({\r\n \r\n /**\r\n * Property: options\r\n * {Object} A reference to options passed to the constructor.\r\n */\r\n options: null,\r\n \r\n /**\r\n * APIProperty: externalProjection\r\n * {} When passed a externalProjection and\r\n * internalProjection, the format will reproject the geometries it\r\n * reads or writes. The externalProjection is the projection used by\r\n * the content which is passed into read or which comes out of write.\r\n * In order to reproject, a projection transformation function for the\r\n * specified projections must be available. This support may be \r\n * provided via proj4js or via a custom transformation function. See\r\n * {} for more information on\r\n * custom transformations.\r\n */\r\n externalProjection: null,\r\n\r\n /**\r\n * APIProperty: internalProjection\r\n * {} When passed a externalProjection and\r\n * internalProjection, the format will reproject the geometries it\r\n * reads or writes. The internalProjection is the projection used by\r\n * the geometries which are returned by read or which are passed into\r\n * write. In order to reproject, a projection transformation function\r\n * for the specified projections must be available. This support may be\r\n * provided via proj4js or via a custom transformation function. See\r\n * {} for more information on\r\n * custom transformations.\r\n */\r\n internalProjection: null,\r\n\r\n /**\r\n * APIProperty: data\r\n * {Object} When is true, this is the parsed string sent to\r\n * .\r\n */\r\n data: null,\r\n\r\n /**\r\n * APIProperty: keepData\r\n * {Object} Maintain a reference () to the most recently read data.\r\n * Default is false.\r\n */\r\n keepData: false,\r\n\r\n /**\r\n * Constructor: OpenLayers.Format\r\n * Instances of this class are not useful. See one of the subclasses.\r\n *\r\n * Parameters:\r\n * options - {Object} An optional object with properties to set on the\r\n * format\r\n *\r\n * Valid options:\r\n * keepData - {Boolean} If true, upon , the data property will be\r\n * set to the parsed object (e.g. the json or xml object).\r\n *\r\n * Returns:\r\n * An instance of OpenLayers.Format\r\n */\r\n initialize: function(options) {\r\n OpenLayers.Util.extend(this, options);\r\n this.options = options;\r\n },\r\n \r\n /**\r\n * APIMethod: destroy\r\n * Clean up.\r\n */\r\n destroy: function() {\r\n },\r\n\r\n /**\r\n * Method: read\r\n * Read data from a string, and return an object whose type depends on the\r\n * subclass. \r\n * \r\n * Parameters:\r\n * data - {string} Data to read/parse.\r\n *\r\n * Returns:\r\n * Depends on the subclass\r\n */\r\n read: function(data) {\r\n throw new Error('Read not implemented.');\r\n },\r\n \r\n /**\r\n * Method: write\r\n * Accept an object, and return a string. \r\n *\r\n * Parameters:\r\n * object - {Object} Object to be serialized\r\n *\r\n * Returns:\r\n * {String} A string representation of the object.\r\n */\r\n write: function(object) {\r\n throw new Error('Write not implemented.');\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Format\"\r\n}); \r\n/* ======================================================================\r\n OpenLayers/Format/XML.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Format.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Format.XML\r\n * Read and write XML. For cross-browser XML generation, use methods on an\r\n * instance of the XML format class instead of on document.\r\n * The DOM creation and traversing methods exposed here all mimic the\r\n * W3C XML DOM methods. Create a new parser with the\r\n * constructor.\r\n *\r\n * Inherits from:\r\n * - \r\n */\r\nOpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {\r\n \r\n /**\r\n * Property: namespaces\r\n * {Object} Mapping of namespace aliases to namespace URIs. Properties\r\n * of this object should not be set individually. Read-only. All\r\n * XML subclasses should have their own namespaces object. Use\r\n * to add or set a namespace alias after construction.\r\n */\r\n namespaces: null,\r\n \r\n /**\r\n * Property: namespaceAlias\r\n * {Object} Mapping of namespace URI to namespace alias. This object\r\n * is read-only. Use to add or set a namespace alias.\r\n */\r\n namespaceAlias: null,\r\n \r\n /**\r\n * Property: defaultPrefix\r\n * {String} The default namespace alias for creating element nodes.\r\n */\r\n defaultPrefix: null,\r\n \r\n /**\r\n * Property: readers\r\n * Contains public functions, grouped by namespace prefix, that will\r\n * be applied when a namespaced node is found matching the function\r\n * name. The function will be applied in the scope of this parser\r\n * with two arguments: the node being read and a context object passed\r\n * from the parent.\r\n */\r\n readers: {},\r\n \r\n /**\r\n * Property: writers\r\n * As a compliment to the property, this structure contains public\r\n * writing functions grouped by namespace alias and named like the\r\n * node names they produce.\r\n */\r\n writers: {},\r\n\r\n /**\r\n * Property: xmldom\r\n * {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM\r\n * object. It is not intended to be a browser sniffing property.\r\n * Instead, the xmldom property is used instead of document\r\n * where namespaced node creation methods are not supported. In all\r\n * other browsers, this remains null.\r\n */\r\n xmldom: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Format.XML\r\n * Construct an XML parser. The parser is used to read and write XML.\r\n * Reading XML from a string returns a DOM element. Writing XML from\r\n * a DOM element returns a string.\r\n *\r\n * Parameters:\r\n * options - {Object} Optional object whose properties will be set on\r\n * the object.\r\n */\r\n initialize: function(options) {\r\n if (OpenLayers.Format.XML.supportActiveX) {\r\n this.xmldom = new ActiveXObject(\"Microsoft.XMLDOM\");\r\n }\r\n OpenLayers.Format.prototype.initialize.apply(this, [options]);\r\n // clone the namespace object and set all namespace aliases\r\n this.namespaces = OpenLayers.Util.extend({}, this.namespaces);\r\n this.namespaceAlias = {};\r\n for(var alias in this.namespaces) {\r\n this.namespaceAlias[this.namespaces[alias]] = alias;\r\n }\r\n },\r\n \r\n /**\r\n * APIMethod: destroy\r\n * Clean up.\r\n */\r\n destroy: function() {\r\n this.xmldom = null;\r\n OpenLayers.Format.prototype.destroy.apply(this, arguments);\r\n },\r\n \r\n /**\r\n * Method: setNamespace\r\n * Set a namespace alias and URI for the format.\r\n *\r\n * Parameters:\r\n * alias - {String} The namespace alias (prefix).\r\n * uri - {String} The namespace URI.\r\n */\r\n setNamespace: function(alias, uri) {\r\n this.namespaces[alias] = uri;\r\n this.namespaceAlias[uri] = alias;\r\n },\r\n\r\n /**\r\n * APIMethod: read\r\n * Deserialize a XML string and return a DOM node.\r\n *\r\n * Parameters:\r\n * text - {String} A XML string\r\n \r\n * Returns:\r\n * {DOMElement} A DOM node\r\n */\r\n read: function(text) {\r\n var index = text.indexOf('<');\r\n if(index > 0) {\r\n text = text.substring(index);\r\n }\r\n var node = OpenLayers.Util.Try(\r\n OpenLayers.Function.bind((\r\n function() {\r\n var xmldom;\r\n /**\r\n * Since we want to be able to call this method on the prototype\r\n * itself, this.xmldom may not exist even if in IE.\r\n */\r\n if (OpenLayers.Format.XML.supportActiveX && !this.xmldom) {\r\n xmldom = new ActiveXObject(\"Microsoft.XMLDOM\");\r\n } else {\r\n xmldom = this.xmldom;\r\n \r\n }\r\n xmldom.loadXML(text);\r\n return xmldom;\r\n }\r\n ), this),\r\n function() {\r\n return new DOMParser().parseFromString(text, 'text/xml');\r\n },\r\n function() {\r\n var req = new XMLHttpRequest();\r\n req.open(\"GET\", \"data:\" + \"text/xml\" +\r\n \";charset=utf-8,\" + encodeURIComponent(text), false);\r\n if(req.overrideMimeType) {\r\n req.overrideMimeType(\"text/xml\");\r\n }\r\n req.send(null);\r\n return req.responseXML;\r\n }\r\n );\r\n\r\n if(this.keepData) {\r\n this.data = node;\r\n }\r\n\r\n return node;\r\n },\r\n\r\n /**\r\n * APIMethod: write\r\n * Serialize a DOM node into a XML string.\r\n * \r\n * Parameters:\r\n * node - {DOMElement} A DOM node.\r\n *\r\n * Returns:\r\n * {String} The XML string representation of the input node.\r\n */\r\n write: function(node) {\r\n var data;\r\n if(this.xmldom) {\r\n data = node.xml;\r\n } else {\r\n var serializer = new XMLSerializer();\r\n if (node.nodeType == 1) {\r\n // Add nodes to a document before serializing. Everything else\r\n // is serialized as is. This may need more work. See #1218 .\r\n var doc = document.implementation.createDocument(\"\", \"\", null);\r\n if (doc.importNode) {\r\n node = doc.importNode(node, true);\r\n }\r\n doc.appendChild(node);\r\n data = serializer.serializeToString(doc);\r\n } else {\r\n data = serializer.serializeToString(node);\r\n }\r\n }\r\n return data;\r\n },\r\n\r\n /**\r\n * APIMethod: createElementNS\r\n * Create a new element with namespace. This node can be appended to\r\n * another node with the standard node.appendChild method. For\r\n * cross-browser support, this method must be used instead of\r\n * document.createElementNS.\r\n *\r\n * Parameters:\r\n * uri - {String} Namespace URI for the element.\r\n * name - {String} The qualified name of the element (prefix:localname).\r\n * \r\n * Returns:\r\n * {Element} A DOM element with namespace.\r\n */\r\n createElementNS: function(uri, name) {\r\n var element;\r\n if(this.xmldom) {\r\n if(typeof uri == \"string\") {\r\n element = this.xmldom.createNode(1, name, uri);\r\n } else {\r\n element = this.xmldom.createNode(1, name, \"\");\r\n }\r\n } else {\r\n element = document.createElementNS(uri, name);\r\n }\r\n return element;\r\n },\r\n\r\n /**\r\n * APIMethod: createDocumentFragment\r\n * Create a document fragment node that can be appended to another node\r\n * created by createElementNS. This will call \r\n * document.createDocumentFragment outside of IE. In IE, the ActiveX\r\n * object's createDocumentFragment method is used.\r\n *\r\n * Returns:\r\n * {Element} A document fragment.\r\n */\r\n createDocumentFragment: function() {\r\n var element;\r\n if (this.xmldom) {\r\n element = this.xmldom.createDocumentFragment();\r\n } else {\r\n element = document.createDocumentFragment();\r\n }\r\n return element;\r\n },\r\n\r\n /**\r\n * APIMethod: createTextNode\r\n * Create a text node. This node can be appended to another node with\r\n * the standard node.appendChild method. For cross-browser support,\r\n * this method must be used instead of document.createTextNode.\r\n * \r\n * Parameters:\r\n * text - {String} The text of the node.\r\n * \r\n * Returns: \r\n * {DOMElement} A DOM text node.\r\n */\r\n createTextNode: function(text) {\r\n var node;\r\n if (typeof text !== \"string\") {\r\n text = String(text);\r\n }\r\n if(this.xmldom) {\r\n node = this.xmldom.createTextNode(text);\r\n } else {\r\n node = document.createTextNode(text);\r\n }\r\n return node;\r\n },\r\n\r\n /**\r\n * APIMethod: getElementsByTagNameNS\r\n * Get a list of elements on a node given the namespace URI and local name.\r\n * To return all nodes in a given namespace, use '*' for the name\r\n * argument. To return all nodes of a given (local) name, regardless\r\n * of namespace, use '*' for the uri argument.\r\n * \r\n * Parameters:\r\n * node - {Element} Node on which to search for other nodes.\r\n * uri - {String} Namespace URI.\r\n * name - {String} Local name of the tag (without the prefix).\r\n * \r\n * Returns:\r\n * {NodeList} A node list or array of elements.\r\n */\r\n getElementsByTagNameNS: function(node, uri, name) {\r\n var elements = [];\r\n if(node.getElementsByTagNameNS) {\r\n elements = node.getElementsByTagNameNS(uri, name);\r\n } else {\r\n // brute force method\r\n var allNodes = node.getElementsByTagName(\"*\");\r\n var potentialNode, fullName;\r\n for(var i=0, len=allNodes.length; i method.\r\n * value - {String} Optional text to be appended as a text node.\r\n *\r\n * Returns:\r\n * {Element} An element node.\r\n */\r\n createElementNSPlus: function(name, options) {\r\n options = options || {};\r\n // order of prefix preference\r\n // 1. in the uri option\r\n // 2. in the prefix option\r\n // 3. in the qualified name\r\n // 4. from the defaultPrefix\r\n var uri = options.uri || this.namespaces[options.prefix];\r\n if(!uri) {\r\n var loc = name.indexOf(\":\");\r\n uri = this.namespaces[name.substring(0, loc)];\r\n }\r\n if(!uri) {\r\n uri = this.namespaces[this.defaultPrefix];\r\n }\r\n var node = this.createElementNS(uri, name);\r\n if(options.attributes) {\r\n this.setAttributes(node, options.attributes);\r\n }\r\n var value = options.value;\r\n if(value != null) {\r\n node.appendChild(this.createTextNode(value));\r\n }\r\n return node;\r\n },\r\n \r\n /**\r\n * Method: setAttributes\r\n * Set multiple attributes given key value pairs from an object.\r\n *\r\n * Parameters:\r\n * node - {Element} An element node.\r\n * obj - {Object || Array} An object whose properties represent attribute\r\n * names and values represent attribute values. If an attribute name\r\n * is a qualified name (\"prefix:local\"), the prefix will be looked up\r\n * in the parsers {namespaces} object. If the prefix is found,\r\n * setAttributeNS will be used instead of setAttribute.\r\n */\r\n setAttributes: function(node, obj) {\r\n var value, uri;\r\n for(var name in obj) {\r\n if(obj[name] != null && obj[name].toString) {\r\n value = obj[name].toString();\r\n // check for qualified attribute name (\"prefix:local\")\r\n uri = this.namespaces[name.substring(0, name.indexOf(\":\"))] || null;\r\n this.setAttributeNS(node, uri, name, value);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Method: getFirstElementChild\r\n * Implementation of firstElementChild attribute that works on ie7 and ie8.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The parent node (required).\r\n *\r\n * Returns:\r\n * {DOMElement} The first child element.\r\n */\r\n getFirstElementChild: function(node) {\r\n if (node.firstElementChild) {\r\n return node.firstElementChild;\r\n }\r\n else {\r\n var child = node.firstChild;\r\n while (child.nodeType != 1 && (child = child.nextSibling)) {}\r\n return child;\r\n }\r\n },\r\n\r\n /**\r\n * Method: readNode\r\n * Shorthand for applying one of the named readers given the node\r\n * namespace and local name. Readers take two args (node, obj) and\r\n * generally extend or modify the second.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The node to be read (required).\r\n * obj - {Object} The object to be modified (optional).\r\n *\r\n * Returns:\r\n * {Object} The input object, modified (or a new one if none was provided).\r\n */\r\n readNode: function(node, obj) {\r\n if(!obj) {\r\n obj = {};\r\n }\r\n var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix];\r\n if(group) {\r\n var local = node.localName || node.nodeName.split(\":\").pop();\r\n var reader = group[local] || group[\"*\"];\r\n if(reader) {\r\n reader.apply(this, [node, obj]);\r\n }\r\n }\r\n return obj;\r\n },\r\n\r\n /**\r\n * Method: readChildNodes\r\n * Shorthand for applying the named readers to all children of a node.\r\n * For each child of type 1 (element), is called.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The node to be read (required).\r\n * obj - {Object} The object to be modified (optional).\r\n *\r\n * Returns:\r\n * {Object} The input object, modified.\r\n */\r\n readChildNodes: function(node, obj) {\r\n if(!obj) {\r\n obj = {};\r\n }\r\n var children = node.childNodes;\r\n var child;\r\n for(var i=0, len=children.length; i group. If a local name is used (e.g. \"Name\") then\r\n * the namespace of the parent is assumed. If a local name is used\r\n * and no parent is supplied, then the default namespace is assumed.\r\n * obj - {Object} Structure containing data for the writer.\r\n * parent - {DOMElement} Result will be appended to this node. If no parent\r\n * is supplied, the node will not be appended to anything.\r\n *\r\n * Returns:\r\n * {DOMElement} The child node.\r\n */\r\n writeNode: function(name, obj, parent) {\r\n var prefix, local;\r\n var split = name.indexOf(\":\");\r\n if(split > 0) {\r\n prefix = name.substring(0, split);\r\n local = name.substring(split + 1);\r\n } else {\r\n if(parent) {\r\n prefix = this.namespaceAlias[parent.namespaceURI];\r\n } else {\r\n prefix = this.defaultPrefix;\r\n }\r\n local = name;\r\n }\r\n var child = this.writers[prefix][local].apply(this, [obj]);\r\n if(parent) {\r\n parent.appendChild(child);\r\n }\r\n return child;\r\n },\r\n\r\n /**\r\n * APIMethod: getChildEl\r\n * Get the first child element. Optionally only return the first child\r\n * if it matches the given name and namespace URI.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The parent node.\r\n * name - {String} Optional node name (local) to search for.\r\n * uri - {String} Optional namespace URI to search for.\r\n *\r\n * Returns:\r\n * {DOMElement} The first child. Returns null if no element is found, if\r\n * something significant besides an element is found, or if the element\r\n * found does not match the optional name and uri.\r\n */\r\n getChildEl: function(node, name, uri) {\r\n return node && this.getThisOrNextEl(node.firstChild, name, uri);\r\n },\r\n \r\n /**\r\n * APIMethod: getNextEl\r\n * Get the next sibling element. Optionally get the first sibling only\r\n * if it matches the given local name and namespace URI.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The node.\r\n * name - {String} Optional local name of the sibling to search for.\r\n * uri - {String} Optional namespace URI of the sibling to search for.\r\n *\r\n * Returns:\r\n * {DOMElement} The next sibling element. Returns null if no element is\r\n * found, something significant besides an element is found, or the\r\n * found element does not match the optional name and uri.\r\n */\r\n getNextEl: function(node, name, uri) {\r\n return node && this.getThisOrNextEl(node.nextSibling, name, uri);\r\n },\r\n \r\n /**\r\n * Method: getThisOrNextEl\r\n * Return this node or the next element node. Optionally get the first\r\n * sibling with the given local name or namespace URI.\r\n *\r\n * Parameters:\r\n * node - {DOMElement} The node.\r\n * name - {String} Optional local name of the sibling to search for.\r\n * uri - {String} Optional namespace URI of the sibling to search for.\r\n *\r\n * Returns:\r\n * {DOMElement} The next sibling element. Returns null if no element is\r\n * found, something significant besides an element is found, or the\r\n * found element does not match the query.\r\n */\r\n getThisOrNextEl: function(node, name, uri) {\r\n outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) {\r\n switch(sibling.nodeType) {\r\n case 1: // Element\r\n if((!name || name === (sibling.localName || sibling.nodeName.split(\":\").pop())) &&\r\n (!uri || uri === sibling.namespaceURI)) {\r\n // matches\r\n break outer;\r\n }\r\n sibling = null;\r\n break outer;\r\n case 3: // Text\r\n if(/^\\s*$/.test(sibling.nodeValue)) {\r\n break;\r\n }\r\n case 4: // CDATA\r\n case 6: // ENTITY_NODE\r\n case 12: // NOTATION_NODE\r\n case 10: // DOCUMENT_TYPE_NODE\r\n case 11: // DOCUMENT_FRAGMENT_NODE\r\n sibling = null;\r\n break outer;\r\n } // ignore comments and processing instructions\r\n }\r\n return sibling || null;\r\n },\r\n \r\n /**\r\n * APIMethod: lookupNamespaceURI\r\n * Takes a prefix and returns the namespace URI associated with it on the given\r\n * node if found (and null if not). Supplying null for the prefix will\r\n * return the default namespace.\r\n *\r\n * For browsers that support it, this calls the native lookupNamesapceURI\r\n * function. In other browsers, this is an implementation of\r\n * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.\r\n *\r\n * For browsers that don't support the attribute.ownerElement property, this\r\n * method cannot be called on attribute nodes.\r\n * \r\n * Parameters:\r\n * node - {DOMElement} The node from which to start looking.\r\n * prefix - {String} The prefix to lookup or null to lookup the default namespace.\r\n * \r\n * Returns:\r\n * {String} The namespace URI for the given prefix. Returns null if the prefix\r\n * cannot be found or the node is the wrong type.\r\n */\r\n lookupNamespaceURI: function(node, prefix) {\r\n var uri = null;\r\n if(node) {\r\n if(node.lookupNamespaceURI) {\r\n uri = node.lookupNamespaceURI(prefix);\r\n } else {\r\n outer: switch(node.nodeType) {\r\n case 1: // ELEMENT_NODE\r\n if(node.namespaceURI !== null && node.prefix === prefix) {\r\n uri = node.namespaceURI;\r\n break outer;\r\n }\r\n var len = node.attributes.length;\r\n if(len) {\r\n var attr;\r\n for(var i=0; i on the instance. On other browsers, this will\r\n * either return an existing or create a new shared document (see\r\n * ).\r\n *\r\n * Returns:\r\n * {XMLDocument}\r\n */\r\n getXMLDoc: function() {\r\n if (!OpenLayers.Format.XML.document && !this.xmldom) {\r\n if (document.implementation && document.implementation.createDocument) {\r\n OpenLayers.Format.XML.document =\r\n document.implementation.createDocument(\"\", \"\", null);\r\n } else if (!this.xmldom && OpenLayers.Format.XML.supportActiveX) {\r\n this.xmldom = new ActiveXObject(\"Microsoft.XMLDOM\");\r\n }\r\n }\r\n return OpenLayers.Format.XML.document || this.xmldom;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Format.XML\" \r\n\r\n}); \r\n\r\nOpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3};\r\n\r\n/**\r\n * APIFunction: OpenLayers.Format.XML.lookupNamespaceURI\r\n * Takes a prefix and returns the namespace URI associated with it on the given\r\n * node if found (and null if not). Supplying null for the prefix will\r\n * return the default namespace.\r\n *\r\n * For browsers that support it, this calls the native lookupNamesapceURI\r\n * function. In other browsers, this is an implementation of\r\n * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.\r\n *\r\n * For browsers that don't support the attribute.ownerElement property, this\r\n * method cannot be called on attribute nodes.\r\n * \r\n * Parameters:\r\n * node - {DOMElement} The node from which to start looking.\r\n * prefix - {String} The prefix to lookup or null to lookup the default namespace.\r\n * \r\n * Returns:\r\n * {String} The namespace URI for the given prefix. Returns null if the prefix\r\n * cannot be found or the node is the wrong type.\r\n */\r\nOpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind(\r\n OpenLayers.Format.XML.prototype.lookupNamespaceURI,\r\n OpenLayers.Format.XML.prototype\r\n);\r\n\r\n/**\r\n * Property: OpenLayers.Format.XML.document\r\n * {XMLDocument} XML document to reuse for creating non-HTML compliant nodes,\r\n * like document.createCDATASection.\r\n */\r\nOpenLayers.Format.XML.document = null;\r\n\r\n/**\r\n * APIFunction: OpenLayers.Format.XML.supportActiveX\r\n * Returns a poolean flag to check if this browser uses ActiveX.\r\n */\r\nOpenLayers.Format.XML.supportActiveX = (function () {\r\n return (Object.getOwnPropertyDescriptor &&\r\n Object.getOwnPropertyDescriptor(window, \"ActiveXObject\")) ||\r\n (\"ActiveXObject\" in window);\r\n})();\r\n/* ======================================================================\r\n OpenLayers/BaseTypes/Date.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/SingleFile.js\r\n */\r\n\r\n/**\r\n * Namespace: OpenLayers.Date\r\n * Contains implementations of Date.parse and date.toISOString that match the\r\n * ECMAScript 5 specification for parsing RFC 3339 dates.\r\n * http://tools.ietf.org/html/rfc3339\r\n */\r\nOpenLayers.Date = {\r\n\r\n /** \r\n * APIProperty: dateRegEx\r\n * The regex to be used for validating dates. You can provide your own\r\n * regex for instance for adding support for years before BC. Default\r\n * value is: /^(?:(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?)?(?:(?:T(\\d{1,2}):(\\d{2}):(\\d{2}(?:\\.\\d+)?)(Z|(?:[+-]\\d{1,2}(?::(\\d{2}))?)))|Z)?$/\r\n */\r\n dateRegEx: /^(?:(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?)?(?:(?:T(\\d{1,2}):(\\d{2}):(\\d{2}(?:\\.\\d+)?)(Z|(?:[+-]\\d{1,2}(?::(\\d{2}))?)))|Z)?$/,\r\n\r\n /**\r\n * APIMethod: toISOString\r\n * Generates a string representing a date. The format of the string follows\r\n * the profile of ISO 8601 for date and time on the Internet (see\r\n * http://tools.ietf.org/html/rfc3339). If the toISOString method is\r\n * available on the Date prototype, that is used. The toISOString\r\n * method for Date instances is defined in ECMA-262.\r\n *\r\n * Parameters:\r\n * date - {Date} A date object.\r\n *\r\n * Returns:\r\n * {String} A string representing the date (e.g.\r\n * \"2010-08-07T16:58:23.123Z\"). If the date does not have a valid time\r\n * (i.e. isNaN(date.getTime())) this method returns the string \"Invalid\r\n * Date\". The ECMA standard says the toISOString method should throw\r\n * RangeError in this case, but Firefox returns a string instead. For\r\n * best results, use isNaN(date.getTime()) to determine date validity\r\n * before generating date strings.\r\n */\r\n toISOString: (function() {\r\n if (\"toISOString\" in Date.prototype) {\r\n return function(date) {\r\n return date.toISOString();\r\n };\r\n } else {\r\n return function(date) {\r\n var str;\r\n if (isNaN(date.getTime())) {\r\n // ECMA-262 says throw RangeError, Firefox returns\r\n // \"Invalid Date\"\r\n str = \"Invalid Date\";\r\n } else {\r\n str =\r\n date.getUTCFullYear() + \"-\" +\r\n OpenLayers.Number.zeroPad(date.getUTCMonth() + 1, 2) + \"-\" +\r\n OpenLayers.Number.zeroPad(date.getUTCDate(), 2) + \"T\" +\r\n OpenLayers.Number.zeroPad(date.getUTCHours(), 2) + \":\" +\r\n OpenLayers.Number.zeroPad(date.getUTCMinutes(), 2) + \":\" +\r\n OpenLayers.Number.zeroPad(date.getUTCSeconds(), 2) + \".\" +\r\n OpenLayers.Number.zeroPad(date.getUTCMilliseconds(), 3) + \"Z\";\r\n }\r\n return str;\r\n };\r\n }\r\n\r\n })(),\r\n\r\n /**\r\n * APIMethod: parse\r\n * Generate a date object from a string. The format for the string follows\r\n * the profile of ISO 8601 for date and time on the Internet (see\r\n * http://tools.ietf.org/html/rfc3339). We don't call the native\r\n * Date.parse because of inconsistency between implmentations. In\r\n * Chrome, calling Date.parse with a string that doesn't contain any\r\n * indication of the timezone (e.g. \"2011\"), the date is interpreted\r\n * in local time. On Firefox, the assumption is UTC.\r\n *\r\n * Parameters:\r\n * str - {String} A string representing the date (e.g.\r\n * \"2010\", \"2010-08\", \"2010-08-07\", \"2010-08-07T16:58:23.123Z\",\r\n * \"2010-08-07T11:58:23.123-06\").\r\n *\r\n * Returns:\r\n * {Date} A date object. If the string could not be parsed, an invalid\r\n * date is returned (i.e. isNaN(date.getTime())).\r\n */\r\n parse: function(str) {\r\n var date;\r\n var match = str.match(this.dateRegEx);\r\n if (match && (match[1] || match[7])) { // must have at least year or time\r\n var year = parseInt(match[1], 10) || 0;\r\n var month = (parseInt(match[2], 10) - 1) || 0;\r\n var day = parseInt(match[3], 10) || 1;\r\n date = new Date(Date.UTC(year, month, day));\r\n // optional time\r\n var type = match[7];\r\n if (type) {\r\n var hours = parseInt(match[4], 10);\r\n var minutes = parseInt(match[5], 10);\r\n var secFrac = parseFloat(match[6]);\r\n var seconds = secFrac | 0;\r\n var milliseconds = Math.round(1000 * (secFrac - seconds));\r\n date.setUTCHours(hours, minutes, seconds, milliseconds);\r\n // check offset\r\n if (type !== \"Z\") {\r\n var hoursOffset = parseInt(type, 10);\r\n var minutesOffset = parseInt(match[8], 10) || 0;\r\n var offset = -1000 * (60 * (hoursOffset * 60) + minutesOffset * 60);\r\n date = new Date(date.getTime() + offset);\r\n }\r\n }\r\n } else {\r\n date = new Date(\"invalid\");\r\n }\r\n return date;\r\n }\r\n};\r\n/* ======================================================================\r\n OpenLayers/Feature.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n * @requires OpenLayers/Util.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Feature\r\n * Features are combinations of geography and attributes. The OpenLayers.Feature\r\n * class specifically combines a marker and a lonlat.\r\n */\r\nOpenLayers.Feature = OpenLayers.Class({\r\n\r\n /** \r\n * Property: layer \r\n * {} \r\n */\r\n layer: null,\r\n\r\n /** \r\n * Property: id \r\n * {String} \r\n */\r\n id: null,\r\n \r\n /** \r\n * Property: lonlat \r\n * {} \r\n */\r\n lonlat: null,\r\n\r\n /** \r\n * Property: data \r\n * {Object} \r\n */\r\n data: null,\r\n\r\n /** \r\n * Property: marker \r\n * {} \r\n */\r\n marker: null,\r\n\r\n /**\r\n * APIProperty: popupClass\r\n * {} The class which will be used to instantiate\r\n * a new Popup. Default is .\r\n */\r\n popupClass: null,\r\n\r\n /** \r\n * Property: popup \r\n * {} \r\n */\r\n popup: null,\r\n\r\n /** \r\n * Constructor: OpenLayers.Feature\r\n * Constructor for features.\r\n *\r\n * Parameters:\r\n * layer - {} \r\n * lonlat - {} \r\n * data - {Object} \r\n * \r\n * Returns:\r\n * {}\r\n */\r\n initialize: function(layer, lonlat, data) {\r\n this.layer = layer;\r\n this.lonlat = lonlat;\r\n this.data = (data != null) ? data : {};\r\n this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\"); \r\n },\r\n\r\n /** \r\n * Method: destroy\r\n * nullify references to prevent circular references and memory leaks\r\n */\r\n destroy: function() {\r\n\r\n //remove the popup from the map\r\n if ((this.layer != null) && (this.layer.map != null)) {\r\n if (this.popup != null) {\r\n this.layer.map.removePopup(this.popup);\r\n }\r\n }\r\n // remove the marker from the layer\r\n if (this.layer != null && this.marker != null) {\r\n this.layer.removeMarker(this.marker);\r\n }\r\n\r\n this.layer = null;\r\n this.id = null;\r\n this.lonlat = null;\r\n this.data = null;\r\n if (this.marker != null) {\r\n this.destroyMarker(this.marker);\r\n this.marker = null;\r\n }\r\n if (this.popup != null) {\r\n this.destroyPopup(this.popup);\r\n this.popup = null;\r\n }\r\n },\r\n \r\n /**\r\n * Method: onScreen\r\n * \r\n * Returns:\r\n * {Boolean} Whether or not the feature is currently visible on screen\r\n * (based on its 'lonlat' property)\r\n */\r\n onScreen:function() {\r\n \r\n var onScreen = false;\r\n if ((this.layer != null) && (this.layer.map != null)) {\r\n var screenBounds = this.layer.map.getExtent();\r\n onScreen = screenBounds.containsLonLat(this.lonlat);\r\n } \r\n return onScreen;\r\n },\r\n \r\n\r\n /**\r\n * Method: createMarker\r\n * Based on the data associated with the Feature, create and return a marker object.\r\n *\r\n * Returns: \r\n * {} A Marker Object created from the 'lonlat' and 'icon' properties\r\n * set in this.data. If no 'lonlat' is set, returns null. If no\r\n * 'icon' is set, OpenLayers.Marker() will load the default image.\r\n * \r\n * Note - this.marker is set to return value\r\n * \r\n */\r\n createMarker: function() {\r\n\r\n if (this.lonlat != null) {\r\n this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon);\r\n }\r\n return this.marker;\r\n },\r\n\r\n /**\r\n * Method: destroyMarker\r\n * Destroys marker.\r\n * If user overrides the createMarker() function, s/he should be able\r\n * to also specify an alternative function for destroying it\r\n */\r\n destroyMarker: function() {\r\n this.marker.destroy(); \r\n },\r\n\r\n /**\r\n * Method: createPopup\r\n * Creates a popup object created from the 'lonlat', 'popupSize',\r\n * and 'popupContentHTML' properties set in this.data. It uses\r\n * this.marker.icon as default anchor. \r\n * \r\n * If no 'lonlat' is set, returns null. \r\n * If no this.marker has been created, no anchor is sent.\r\n *\r\n * Note - the returned popup object is 'owned' by the feature, so you\r\n * cannot use the popup's destroy method to discard the popup.\r\n * Instead, you must use the feature's destroyPopup\r\n * \r\n * Note - this.popup is set to return value\r\n * \r\n * Parameters: \r\n * closeBox - {Boolean} create popup with closebox or not\r\n * \r\n * Returns:\r\n * {} Returns the created popup, which is also set\r\n * as 'popup' property of this feature. Will be of whatever type\r\n * specified by this feature's 'popupClass' property, but must be\r\n * of type .\r\n * \r\n */\r\n createPopup: function(closeBox) {\r\n\r\n if (this.lonlat != null) {\r\n if (!this.popup) {\r\n var anchor = (this.marker) ? this.marker.icon : null;\r\n var popupClass = this.popupClass ? \r\n this.popupClass : OpenLayers.Popup.Anchored;\r\n this.popup = new popupClass(this.id + \"_popup\", \r\n this.lonlat,\r\n this.data.popupSize,\r\n this.data.popupContentHTML,\r\n anchor, \r\n closeBox); \r\n } \r\n if (this.data.overflow != null) {\r\n this.popup.contentDiv.style.overflow = this.data.overflow;\r\n } \r\n \r\n this.popup.feature = this;\r\n } \r\n return this.popup;\r\n },\r\n\r\n \r\n /**\r\n * Method: destroyPopup\r\n * Destroys the popup created via createPopup.\r\n *\r\n * As with the marker, if user overrides the createPopup() function, s/he \r\n * should also be able to override the destruction\r\n */\r\n destroyPopup: function() {\r\n if (this.popup) {\r\n this.popup.feature = null;\r\n this.popup.destroy();\r\n this.popup = null;\r\n } \r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Feature\"\r\n});\r\n/* ======================================================================\r\n OpenLayers/Feature/Vector.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n// TRASH THIS\r\nOpenLayers.State = {\r\n /** states */\r\n UNKNOWN: 'Unknown',\r\n INSERT: 'Insert',\r\n UPDATE: 'Update',\r\n DELETE: 'Delete'\r\n};\r\n\r\n/**\r\n * @requires OpenLayers/Feature.js\r\n * @requires OpenLayers/Util.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Feature.Vector\r\n * Vector features use the OpenLayers.Geometry classes as geometry description.\r\n * They have an 'attributes' property, which is the data object, and a 'style'\r\n * property, the default values of which are defined in the \r\n * objects.\r\n * \r\n * Inherits from:\r\n * - \r\n */\r\nOpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {\r\n\r\n /** \r\n * Property: fid \r\n * {String} \r\n */\r\n fid: null,\r\n \r\n /** \r\n * APIProperty: geometry \r\n * {} \r\n */\r\n geometry: null,\r\n\r\n /** \r\n * APIProperty: attributes \r\n * {Object} This object holds arbitrary, serializable properties that\r\n * describe the feature.\r\n */\r\n attributes: null,\r\n\r\n /**\r\n * Property: bounds\r\n * {} The box bounding that feature's geometry, that\r\n * property can be set by an object when\r\n * deserializing the feature, so in most cases it represents an\r\n * information set by the server. \r\n */\r\n bounds: null,\r\n\r\n /** \r\n * Property: state \r\n * {String} \r\n */\r\n state: null,\r\n \r\n /** \r\n * APIProperty: style \r\n * {Object} \r\n */\r\n style: null,\r\n\r\n /**\r\n * APIProperty: url\r\n * {String} If this property is set it will be taken into account by\r\n * {} when updating or deleting the feature.\r\n */\r\n url: null,\r\n \r\n /**\r\n * Property: renderIntent\r\n * {String} rendering intent currently being used\r\n */\r\n renderIntent: \"default\",\r\n \r\n /**\r\n * APIProperty: modified\r\n * {Object} An object with the originals of the geometry and attributes of\r\n * the feature, if they were changed. Currently this property is only read\r\n * by , and written by\r\n * , which sets the geometry property.\r\n * Applications can set the originals of modified attributes in the\r\n * attributes property. Note that applications have to check if this\r\n * object and the attributes property is already created before using it.\r\n * After a change made with ModifyFeature, this object could look like\r\n *\r\n * (code)\r\n * {\r\n * geometry: >Object\r\n * }\r\n * (end)\r\n *\r\n * When an application has made changes to feature attributes, it could\r\n * have set the attributes to something like this:\r\n *\r\n * (code)\r\n * {\r\n * attributes: {\r\n * myAttribute: \"original\"\r\n * }\r\n * }\r\n * (end)\r\n *\r\n * Note that only checks for truthy values in\r\n * *modified.geometry* and the attribute names in *modified.attributes*,\r\n * but it is recommended to set the original values (and not just true) as\r\n * attribute value, so applications could use this information to undo\r\n * changes.\r\n */\r\n modified: null,\r\n\r\n /** \r\n * Constructor: OpenLayers.Feature.Vector\r\n * Create a vector feature. \r\n * \r\n * Parameters:\r\n * geometry - {} The geometry that this feature\r\n * represents.\r\n * attributes - {Object} An optional object that will be mapped to the\r\n * property. \r\n * style - {Object} An optional style object.\r\n */\r\n initialize: function(geometry, attributes, style) {\r\n OpenLayers.Feature.prototype.initialize.apply(this,\r\n [null, null, attributes]);\r\n this.lonlat = null;\r\n this.geometry = geometry ? geometry : null;\r\n this.state = null;\r\n this.attributes = {};\r\n if (attributes) {\r\n this.attributes = OpenLayers.Util.extend(this.attributes,\r\n attributes);\r\n }\r\n this.style = style ? style : null; \r\n },\r\n \r\n /** \r\n * Method: destroy\r\n * nullify references to prevent circular references and memory leaks\r\n */\r\n destroy: function() {\r\n if (this.layer) {\r\n this.layer.removeFeatures(this);\r\n this.layer = null;\r\n }\r\n \r\n this.geometry = null;\r\n this.modified = null;\r\n OpenLayers.Feature.prototype.destroy.apply(this, arguments);\r\n },\r\n \r\n /**\r\n * Method: clone\r\n * Create a clone of this vector feature. Does not set any non-standard\r\n * properties.\r\n *\r\n * Returns:\r\n * {} An exact clone of this vector feature.\r\n */\r\n clone: function () {\r\n return new OpenLayers.Feature.Vector(\r\n this.geometry ? this.geometry.clone() : null,\r\n this.attributes,\r\n this.style);\r\n },\r\n\r\n /**\r\n * Method: onScreen\r\n * Determine whether the feature is within the map viewport. This method\r\n * tests for an intersection between the geometry and the viewport\r\n * bounds. If a more efficient but less precise geometry bounds\r\n * intersection is desired, call the method with the boundsOnly\r\n * parameter true.\r\n *\r\n * Parameters:\r\n * boundsOnly - {Boolean} Only test whether a feature's bounds intersects\r\n * the viewport bounds. Default is false. If false, the feature's\r\n * geometry must intersect the viewport for onScreen to return true.\r\n * \r\n * Returns:\r\n * {Boolean} The feature is currently visible on screen (optionally\r\n * based on its bounds if boundsOnly is true).\r\n */\r\n onScreen:function(boundsOnly) {\r\n var onScreen = false;\r\n if(this.layer && this.layer.map) {\r\n var screenBounds = this.layer.map.getExtent();\r\n if(boundsOnly) {\r\n var featureBounds = this.geometry.getBounds();\r\n onScreen = screenBounds.intersectsBounds(featureBounds);\r\n } else {\r\n var screenPoly = screenBounds.toGeometry();\r\n onScreen = screenPoly.intersects(this.geometry);\r\n }\r\n } \r\n return onScreen;\r\n },\r\n\r\n /**\r\n * Method: getVisibility\r\n * Determine whether the feature is displayed or not. It may not displayed\r\n * because:\r\n * - its style display property is set to 'none',\r\n * - it doesn't belong to any layer,\r\n * - the styleMap creates a symbolizer with display property set to 'none'\r\n * for it,\r\n * - the layer which it belongs to is not visible.\r\n * \r\n * Returns:\r\n * {Boolean} The feature is currently displayed.\r\n */\r\n getVisibility: function() {\r\n return !(this.style && this.style.display == 'none' ||\r\n !this.layer ||\r\n this.layer && this.layer.styleMap &&\r\n this.layer.styleMap.createSymbolizer(this, this.renderIntent).display == 'none' ||\r\n this.layer && !this.layer.getVisibility());\r\n },\r\n \r\n /**\r\n * Method: createMarker\r\n * HACK - we need to decide if all vector features should be able to\r\n * create markers\r\n * \r\n * Returns:\r\n * {} For now just returns null\r\n */\r\n createMarker: function() {\r\n return null;\r\n },\r\n\r\n /**\r\n * Method: destroyMarker\r\n * HACK - we need to decide if all vector features should be able to\r\n * delete markers\r\n * \r\n * If user overrides the createMarker() function, s/he should be able\r\n * to also specify an alternative function for destroying it\r\n */\r\n destroyMarker: function() {\r\n // pass\r\n },\r\n\r\n /**\r\n * Method: createPopup\r\n * HACK - we need to decide if all vector features should be able to\r\n * create popups\r\n * \r\n * Returns:\r\n * {} For now just returns null\r\n */\r\n createPopup: function() {\r\n return null;\r\n },\r\n\r\n /**\r\n * Method: atPoint\r\n * Determins whether the feature intersects with the specified location.\r\n * \r\n * Parameters: \r\n * lonlat - {|Object} OpenLayers.LonLat or an\r\n * object with a 'lon' and 'lat' properties.\r\n * toleranceLon - {float} Optional tolerance in Geometric Coords\r\n * toleranceLat - {float} Optional tolerance in Geographic Coords\r\n * \r\n * Returns:\r\n * {Boolean} Whether or not the feature is at the specified location\r\n */\r\n atPoint: function(lonlat, toleranceLon, toleranceLat) {\r\n var atPoint = false;\r\n if(this.geometry) {\r\n atPoint = this.geometry.atPoint(lonlat, toleranceLon, \r\n toleranceLat);\r\n }\r\n return atPoint;\r\n },\r\n\r\n /**\r\n * Method: destroyPopup\r\n * HACK - we need to decide if all vector features should be able to\r\n * delete popups\r\n */\r\n destroyPopup: function() {\r\n // pass\r\n },\r\n\r\n /**\r\n * Method: move\r\n * Moves the feature and redraws it at its new location\r\n *\r\n * Parameters:\r\n * location - { or } the\r\n * location to which to move the feature.\r\n */\r\n move: function(location) {\r\n\r\n if(!this.layer || !this.geometry.move){\r\n //do nothing if no layer or immoveable geometry\r\n return undefined;\r\n }\r\n\r\n var pixel;\r\n if (location.CLASS_NAME == \"OpenLayers.LonLat\") {\r\n pixel = this.layer.getViewPortPxFromLonLat(location);\r\n } else {\r\n pixel = location;\r\n }\r\n \r\n var lastPixel = this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());\r\n var res = this.layer.map.getResolution();\r\n this.geometry.move(res * (pixel.x - lastPixel.x),\r\n res * (lastPixel.y - pixel.y));\r\n this.layer.drawFeature(this);\r\n return lastPixel;\r\n },\r\n \r\n /**\r\n * Method: toState\r\n * Sets the new state\r\n *\r\n * Parameters:\r\n * state - {String} \r\n */\r\n toState: function(state) {\r\n if (state == OpenLayers.State.UPDATE) {\r\n switch (this.state) {\r\n case OpenLayers.State.UNKNOWN:\r\n case OpenLayers.State.DELETE:\r\n this.state = state;\r\n break;\r\n case OpenLayers.State.UPDATE:\r\n case OpenLayers.State.INSERT:\r\n break;\r\n }\r\n } else if (state == OpenLayers.State.INSERT) {\r\n switch (this.state) {\r\n case OpenLayers.State.UNKNOWN:\r\n break;\r\n default:\r\n this.state = state;\r\n break;\r\n }\r\n } else if (state == OpenLayers.State.DELETE) {\r\n switch (this.state) {\r\n case OpenLayers.State.INSERT:\r\n // the feature should be destroyed\r\n break;\r\n case OpenLayers.State.DELETE:\r\n break;\r\n case OpenLayers.State.UNKNOWN:\r\n case OpenLayers.State.UPDATE:\r\n this.state = state;\r\n break;\r\n }\r\n } else if (state == OpenLayers.State.UNKNOWN) {\r\n this.state = state;\r\n }\r\n },\r\n \r\n CLASS_NAME: \"OpenLayers.Feature.Vector\"\r\n});\r\n\r\n\r\n/**\r\n * Constant: OpenLayers.Feature.Vector.style\r\n * OpenLayers features can have a number of style attributes. The 'default' \r\n * style will typically be used if no other style is specified. These\r\n * styles correspond for the most part, to the styling properties defined\r\n * by the SVG standard. \r\n * Information on fill properties: http://www.w3.org/TR/SVG/painting.html#FillProperties\r\n * Information on stroke properties: http://www.w3.org/TR/SVG/painting.html#StrokeProperties\r\n *\r\n * Symbolizer properties:\r\n * fill - {Boolean} Set to false if no fill is desired.\r\n * fillColor - {String} Hex fill color. Default is \"#ee9900\".\r\n * fillOpacity - {Number} Fill opacity (0-1). Default is 0.4 \r\n * stroke - {Boolean} Set to false if no stroke is desired.\r\n * strokeColor - {String} Hex stroke color. Default is \"#ee9900\".\r\n * strokeOpacity - {Number} Stroke opacity (0-1). Default is 1.\r\n * strokeWidth - {Number} Pixel stroke width. Default is 1.\r\n * strokeLinecap - {String} Stroke cap type. Default is \"round\". [butt | round | square]\r\n * strokeDashstyle - {String} Stroke dash style. Default is \"solid\". [dot | dash | dashdot | longdash | longdashdot | solid]\r\n * graphic - {Boolean} Set to false if no graphic is desired.\r\n * pointRadius - {Number} Pixel point radius. Default is 6.\r\n * pointerEvents - {String} Default is \"visiblePainted\".\r\n * cursor - {String} Default is \"\".\r\n * externalGraphic - {String} Url to an external graphic that will be used for rendering points.\r\n * graphicWidth - {Number} Pixel width for sizing an external graphic.\r\n * graphicHeight - {Number} Pixel height for sizing an external graphic.\r\n * graphicOpacity - {Number} Opacity (0-1) for an external graphic.\r\n * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic.\r\n * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic.\r\n * rotation - {Number} For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point (or any point off center as specified by graphicXOffset and graphicYOffset).\r\n * graphicZIndex - {Number} The integer z-index value to use in rendering.\r\n * graphicName - {String} Named graphic to use when rendering points. Supported values include \"circle\" (default),\r\n * \"square\", \"star\", \"x\", \"cross\", \"triangle\".\r\n * graphicTitle - {String} Tooltip when hovering over a feature. *deprecated*, use title instead\r\n * title - {String} Tooltip when hovering over a feature. Not supported by the canvas renderer.\r\n * backgroundGraphic - {String} Url to a graphic to be used as the background under an externalGraphic.\r\n * backgroundGraphicZIndex - {Number} The integer z-index value to use in rendering the background graphic.\r\n * backgroundXOffset - {Number} The x offset (in pixels) for the background graphic.\r\n * backgroundYOffset - {Number} The y offset (in pixels) for the background graphic.\r\n * backgroundHeight - {Number} The height of the background graphic. If not provided, the graphicHeight will be used.\r\n * backgroundWidth - {Number} The width of the background width. If not provided, the graphicWidth will be used.\r\n * label - {String} The text for an optional label. For browsers that use the canvas renderer, this requires either\r\n * fillText or mozDrawText to be available.\r\n * labelAlign - {String} Label alignment. This specifies the insertion point relative to the text. It is a string\r\n * composed of two characters. The first character is for the horizontal alignment, the second for the vertical\r\n * alignment. Valid values for horizontal alignment: \"l\"=left, \"c\"=center, \"r\"=right. Valid values for vertical\r\n * alignment: \"t\"=top, \"m\"=middle, \"b\"=bottom. Example values: \"lt\", \"cm\", \"rb\". Default is \"cm\".\r\n * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label. Not supported by the canvas renderer.\r\n * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label. Not supported by the canvas renderer.\r\n * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls.\r\n * Default is false.\r\n * labelOutlineColor - {String} The color of the label outline. Default is 'white'. Only supported by the canvas & SVG renderers.\r\n * labelOutlineWidth - {Number} The width of the label outline. Default is 3, set to 0 or null to disable. Only supported by the SVG renderers.\r\n * labelOutlineOpacity - {Number} The opacity (0-1) of the label outline. Default is fontOpacity. Only supported by the canvas & SVG renderers.\r\n * fontColor - {String} The font color for the label, to be provided like CSS.\r\n * fontOpacity - {Number} Opacity (0-1) for the label\r\n * fontFamily - {String} The font family for the label, to be provided like in CSS.\r\n * fontSize - {String} The font size for the label, to be provided like in CSS.\r\n * fontStyle - {String} The font style for the label, to be provided like in CSS.\r\n * fontWeight - {String} The font weight for the label, to be provided like in CSS.\r\n * display - {String} Symbolizers will have no effect if display is set to \"none\". All other values have no effect.\r\n */ \r\nOpenLayers.Feature.Vector.style = {\r\n 'default': {\r\n fillColor: \"#ee9900\",\r\n fillOpacity: 0.4, \r\n hoverFillColor: \"white\",\r\n hoverFillOpacity: 0.8,\r\n strokeColor: \"#ee9900\",\r\n strokeOpacity: 1,\r\n strokeWidth: 1,\r\n strokeLinecap: \"round\",\r\n strokeDashstyle: \"solid\",\r\n hoverStrokeColor: \"red\",\r\n hoverStrokeOpacity: 1,\r\n hoverStrokeWidth: 0.2,\r\n pointRadius: 6,\r\n hoverPointRadius: 1,\r\n hoverPointUnit: \"%\",\r\n pointerEvents: \"visiblePainted\",\r\n cursor: \"inherit\",\r\n fontColor: \"#000000\",\r\n labelAlign: \"cm\",\r\n labelOutlineColor: \"white\",\r\n labelOutlineWidth: 3\r\n },\r\n 'select': {\r\n fillColor: \"blue\",\r\n fillOpacity: 0.4, \r\n hoverFillColor: \"white\",\r\n hoverFillOpacity: 0.8,\r\n strokeColor: \"blue\",\r\n strokeOpacity: 1,\r\n strokeWidth: 2,\r\n strokeLinecap: \"round\",\r\n strokeDashstyle: \"solid\",\r\n hoverStrokeColor: \"red\",\r\n hoverStrokeOpacity: 1,\r\n hoverStrokeWidth: 0.2,\r\n pointRadius: 6,\r\n hoverPointRadius: 1,\r\n hoverPointUnit: \"%\",\r\n pointerEvents: \"visiblePainted\",\r\n cursor: \"pointer\",\r\n fontColor: \"#000000\",\r\n labelAlign: \"cm\",\r\n labelOutlineColor: \"white\",\r\n labelOutlineWidth: 3\r\n\r\n },\r\n 'temporary': {\r\n fillColor: \"#66cccc\",\r\n fillOpacity: 0.2, \r\n hoverFillColor: \"white\",\r\n hoverFillOpacity: 0.8,\r\n strokeColor: \"#66cccc\",\r\n strokeOpacity: 1,\r\n strokeLinecap: \"round\",\r\n strokeWidth: 2,\r\n strokeDashstyle: \"solid\",\r\n hoverStrokeColor: \"red\",\r\n hoverStrokeOpacity: 1,\r\n hoverStrokeWidth: 0.2,\r\n pointRadius: 6,\r\n hoverPointRadius: 1,\r\n hoverPointUnit: \"%\",\r\n pointerEvents: \"visiblePainted\",\r\n cursor: \"inherit\",\r\n fontColor: \"#000000\",\r\n labelAlign: \"cm\",\r\n labelOutlineColor: \"white\",\r\n labelOutlineWidth: 3\r\n\r\n },\r\n 'delete': {\r\n display: \"none\"\r\n }\r\n}; \r\n/* ======================================================================\r\n OpenLayers/Geometry.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n \r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Geometry\r\n * A Geometry is a description of a geographic object. Create an instance of\r\n * this class with the constructor. This is a base class,\r\n * typical geometry types are described by subclasses of this class.\r\n *\r\n * Note that if you use the method, you must\r\n * explicitly include the OpenLayers.Format.WKT in your build.\r\n */\r\nOpenLayers.Geometry = OpenLayers.Class({\r\n\r\n /**\r\n * Property: id\r\n * {String} A unique identifier for this geometry.\r\n */\r\n id: null,\r\n\r\n /**\r\n * Property: parent\r\n * {}This is set when a Geometry is added as component\r\n * of another geometry\r\n */\r\n parent: null,\r\n\r\n /**\r\n * Property: bounds \r\n * {} The bounds of this geometry\r\n */\r\n bounds: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry\r\n * Creates a geometry object. \r\n */\r\n initialize: function() {\r\n this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME+ \"_\");\r\n },\r\n \r\n /**\r\n * Method: destroy\r\n * Destroy this geometry.\r\n */\r\n destroy: function() {\r\n this.id = null;\r\n this.bounds = null;\r\n },\r\n \r\n /**\r\n * APIMethod: clone\r\n * Create a clone of this geometry. Does not set any non-standard\r\n * properties of the cloned geometry.\r\n * \r\n * Returns:\r\n * {} An exact clone of this geometry.\r\n */\r\n clone: function() {\r\n return new OpenLayers.Geometry();\r\n },\r\n \r\n /**\r\n * Method: setBounds\r\n * Set the bounds for this Geometry.\r\n * \r\n * Parameters:\r\n * bounds - {} \r\n */\r\n setBounds: function(bounds) {\r\n if (bounds) {\r\n this.bounds = bounds.clone();\r\n }\r\n },\r\n \r\n /**\r\n * Method: clearBounds\r\n * Nullify this components bounds and that of its parent as well.\r\n */\r\n clearBounds: function() {\r\n this.bounds = null;\r\n if (this.parent) {\r\n this.parent.clearBounds();\r\n } \r\n },\r\n \r\n /**\r\n * Method: extendBounds\r\n * Extend the existing bounds to include the new bounds. \r\n * If geometry's bounds is not yet set, then set a new Bounds.\r\n * \r\n * Parameters:\r\n * newBounds - {} \r\n */\r\n extendBounds: function(newBounds){\r\n var bounds = this.getBounds();\r\n if (!bounds) {\r\n this.setBounds(newBounds);\r\n } else {\r\n this.bounds.extend(newBounds);\r\n }\r\n },\r\n \r\n /**\r\n * APIMethod: getBounds\r\n * Get the bounds for this Geometry. If bounds is not set, it \r\n * is calculated again, this makes queries faster.\r\n * \r\n * Returns:\r\n * {}\r\n */\r\n getBounds: function() {\r\n if (this.bounds == null) {\r\n this.calculateBounds();\r\n }\r\n return this.bounds;\r\n },\r\n \r\n /** \r\n * APIMethod: calculateBounds\r\n * Recalculate the bounds for the geometry. \r\n */\r\n calculateBounds: function() {\r\n //\r\n // This should be overridden by subclasses.\r\n //\r\n },\r\n \r\n /**\r\n * APIMethod: distanceTo\r\n * Calculate the closest distance between two geometries (on the x-y plane).\r\n *\r\n * Parameters:\r\n * geometry - {} The target geometry.\r\n * options - {Object} Optional properties for configuring the distance\r\n * calculation.\r\n *\r\n * Valid options depend on the specific geometry type.\r\n * \r\n * Returns:\r\n * {Number | Object} The distance between this geometry and the target.\r\n * If details is true, the return will be an object with distance,\r\n * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\r\n * the coordinates of the closest point on this geometry. The x1 and y1\r\n * properties represent the coordinates of the closest point on the\r\n * target geometry.\r\n */\r\n distanceTo: function(geometry, options) {\r\n },\r\n \r\n /**\r\n * APIMethod: getVertices\r\n * Return a list of all points in this geometry.\r\n *\r\n * Parameters:\r\n * nodes - {Boolean} For lines, only return vertices that are\r\n * endpoints. If false, for lines, only vertices that are not\r\n * endpoints will be returned. If not provided, all vertices will\r\n * be returned.\r\n *\r\n * Returns:\r\n * {Array} A list of all vertices in the geometry.\r\n */\r\n getVertices: function(nodes) {\r\n },\r\n\r\n /**\r\n * Method: atPoint\r\n * Note - This is only an approximation based on the bounds of the \r\n * geometry.\r\n * \r\n * Parameters:\r\n * lonlat - {|Object} OpenLayers.LonLat or an\r\n * object with a 'lon' and 'lat' properties.\r\n * toleranceLon - {float} Optional tolerance in Geometric Coords\r\n * toleranceLat - {float} Optional tolerance in Geographic Coords\r\n * \r\n * Returns:\r\n * {Boolean} Whether or not the geometry is at the specified location\r\n */\r\n atPoint: function(lonlat, toleranceLon, toleranceLat) {\r\n var atPoint = false;\r\n var bounds = this.getBounds();\r\n if ((bounds != null) && (lonlat != null)) {\r\n\r\n var dX = (toleranceLon != null) ? toleranceLon : 0;\r\n var dY = (toleranceLat != null) ? toleranceLat : 0;\r\n \r\n var toleranceBounds = \r\n new OpenLayers.Bounds(this.bounds.left - dX,\r\n this.bounds.bottom - dY,\r\n this.bounds.right + dX,\r\n this.bounds.top + dY);\r\n\r\n atPoint = toleranceBounds.containsLonLat(lonlat);\r\n }\r\n return atPoint;\r\n },\r\n \r\n /**\r\n * Method: getLength\r\n * Calculate the length of this geometry. This method is defined in\r\n * subclasses.\r\n * \r\n * Returns:\r\n * {Float} The length of the collection by summing its parts\r\n */\r\n getLength: function() {\r\n //to be overridden by geometries that actually have a length\r\n //\r\n return 0.0;\r\n },\r\n\r\n /**\r\n * Method: getArea\r\n * Calculate the area of this geometry. This method is defined in subclasses.\r\n * \r\n * Returns:\r\n * {Float} The area of the collection by summing its parts\r\n */\r\n getArea: function() {\r\n //to be overridden by geometries that actually have an area\r\n //\r\n return 0.0;\r\n },\r\n \r\n /**\r\n * APIMethod: getCentroid\r\n * Calculate the centroid of this geometry. This method is defined in subclasses.\r\n *\r\n * Returns:\r\n * {} The centroid of the collection\r\n */\r\n getCentroid: function() {\r\n return null;\r\n },\r\n\r\n /**\r\n * Method: toString\r\n * Returns a text representation of the geometry. If the WKT format is\r\n * included in a build, this will be the Well-Known Text \r\n * representation.\r\n *\r\n * Returns:\r\n * {String} String representation of this geometry.\r\n */\r\n toString: function() {\r\n var string;\r\n if (OpenLayers.Format && OpenLayers.Format.WKT) {\r\n string = OpenLayers.Format.WKT.prototype.write(\r\n new OpenLayers.Feature.Vector(this)\r\n );\r\n } else {\r\n string = Object.prototype.toString.call(this);\r\n }\r\n return string;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Geometry\"\r\n});\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.fromWKT\r\n * Generate a geometry given a Well-Known Text string. For this method to\r\n * work, you must include the OpenLayers.Format.WKT in your build \r\n * explicitly.\r\n *\r\n * Parameters:\r\n * wkt - {String} A string representing the geometry in Well-Known Text.\r\n *\r\n * Returns:\r\n * {} A geometry of the appropriate class.\r\n */\r\nOpenLayers.Geometry.fromWKT = function(wkt) {\r\n var geom;\r\n if (OpenLayers.Format && OpenLayers.Format.WKT) {\r\n var format = OpenLayers.Geometry.fromWKT.format;\r\n if (!format) {\r\n format = new OpenLayers.Format.WKT();\r\n OpenLayers.Geometry.fromWKT.format = format;\r\n }\r\n var result = format.read(wkt);\r\n if (result instanceof OpenLayers.Feature.Vector) {\r\n geom = result.geometry;\r\n } else if (OpenLayers.Util.isArray(result)) {\r\n var len = result.length;\r\n var components = new Array(len);\r\n for (var i=0; i= seg2.x1 || seg2.x2 >= seg1.x1. In those\r\n * obvious cases where there is no intersection, the function should\r\n * not be called.\r\n *\r\n * Parameters:\r\n * seg1 - {Object} Object representing a segment with properties x1, y1, x2,\r\n * and y2. The start point is represented by x1 and y1. The end point\r\n * is represented by x2 and y2. Start and end are ordered so that x1 < x2.\r\n * seg2 - {Object} Object representing a segment with properties x1, y1, x2,\r\n * and y2. The start point is represented by x1 and y1. The end point\r\n * is represented by x2 and y2. Start and end are ordered so that x1 < x2.\r\n * options - {Object} Optional properties for calculating the intersection.\r\n *\r\n * Valid options:\r\n * point - {Boolean} Return the intersection point. If false, the actual\r\n * intersection point will not be calculated. If true and the segments\r\n * intersect, the intersection point will be returned. If true and\r\n * the segments do not intersect, false will be returned. If true and\r\n * the segments are coincident, true will be returned.\r\n * tolerance - {Number} If a non-null value is provided, if the segments are\r\n * within the tolerance distance, this will be considered an intersection.\r\n * In addition, if the point option is true and the calculated intersection\r\n * is within the tolerance distance of an end point, the endpoint will be\r\n * returned instead of the calculated intersection. Further, if the\r\n * intersection is within the tolerance of endpoints on both segments, or\r\n * if two segment endpoints are within the tolerance distance of eachother\r\n * (but no intersection is otherwise calculated), an endpoint on the\r\n * first segment provided will be returned.\r\n *\r\n * Returns:\r\n * {Boolean | } The two segments intersect.\r\n * If the point argument is true, the return will be the intersection\r\n * point or false if none exists. If point is true and the segments\r\n * are coincident, return will be true (and the instersection is equal\r\n * to the shorter segment).\r\n */\r\nOpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {\r\n var point = options && options.point;\r\n var tolerance = options && options.tolerance;\r\n var intersection = false;\r\n var x11_21 = seg1.x1 - seg2.x1;\r\n var y11_21 = seg1.y1 - seg2.y1;\r\n var x12_11 = seg1.x2 - seg1.x1;\r\n var y12_11 = seg1.y2 - seg1.y1;\r\n var y22_21 = seg2.y2 - seg2.y1;\r\n var x22_21 = seg2.x2 - seg2.x1;\r\n var d = (y22_21 * x12_11) - (x22_21 * y12_11);\r\n var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);\r\n var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);\r\n if(d == 0) {\r\n // parallel\r\n if(n1 == 0 && n2 == 0) {\r\n // coincident\r\n intersection = true;\r\n }\r\n } else {\r\n var along1 = n1 / d;\r\n var along2 = n2 / d;\r\n if(along1 >= 0 && along1 <= 1 && along2 >=0 && along2 <= 1) {\r\n // intersect\r\n if(!point) {\r\n intersection = true;\r\n } else {\r\n // calculate the intersection point\r\n var x = seg1.x1 + (along1 * x12_11);\r\n var y = seg1.y1 + (along1 * y12_11);\r\n intersection = new OpenLayers.Geometry.Point(x, y);\r\n }\r\n }\r\n }\r\n if(tolerance) {\r\n var dist;\r\n if(intersection) {\r\n if(point) {\r\n var segs = [seg1, seg2];\r\n var seg, x, y;\r\n // check segment endpoints for proximity to intersection\r\n // set intersection to first endpoint within the tolerance\r\n outer: for(var i=0; i<2; ++i) {\r\n seg = segs[i];\r\n for(var j=1; j<3; ++j) {\r\n x = seg[\"x\" + j];\r\n y = seg[\"y\" + j];\r\n dist = Math.sqrt(\r\n Math.pow(x - intersection.x, 2) +\r\n Math.pow(y - intersection.y, 2)\r\n );\r\n if(dist < tolerance) {\r\n intersection.x = x;\r\n intersection.y = y;\r\n break outer;\r\n }\r\n }\r\n }\r\n \r\n }\r\n } else {\r\n // no calculated intersection, but segments could be within\r\n // the tolerance of one another\r\n var segs = [seg1, seg2];\r\n var source, target, x, y, p, result;\r\n // check segment endpoints for proximity to intersection\r\n // set intersection to first endpoint within the tolerance\r\n outer: for(var i=0; i<2; ++i) {\r\n source = segs[i];\r\n target = segs[(i+1)%2];\r\n for(var j=1; j<3; ++j) {\r\n p = {x: source[\"x\"+j], y: source[\"y\"+j]};\r\n result = OpenLayers.Geometry.distanceToSegment(p, target);\r\n if(result.distance < tolerance) {\r\n if(point) {\r\n intersection = new OpenLayers.Geometry.Point(p.x, p.y);\r\n } else {\r\n intersection = true;\r\n }\r\n break outer;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return intersection;\r\n};\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.distanceToSegment\r\n *\r\n * Parameters:\r\n * point - {Object} An object with x and y properties representing the\r\n * point coordinates.\r\n * segment - {Object} An object with x1, y1, x2, and y2 properties\r\n * representing endpoint coordinates.\r\n *\r\n * Returns:\r\n * {Object} An object with distance, along, x, and y properties. The distance\r\n * will be the shortest distance between the input point and segment.\r\n * The x and y properties represent the coordinates along the segment\r\n * where the shortest distance meets the segment. The along attribute\r\n * describes how far between the two segment points the given point is.\r\n */\r\nOpenLayers.Geometry.distanceToSegment = function(point, segment) {\r\n var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment);\r\n result.distance = Math.sqrt(result.distance);\r\n return result;\r\n};\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.distanceSquaredToSegment\r\n *\r\n * Usually the distanceToSegment function should be used. This variant however\r\n * can be used for comparisons where the exact distance is not important.\r\n *\r\n * Parameters:\r\n * point - {Object} An object with x and y properties representing the\r\n * point coordinates.\r\n * segment - {Object} An object with x1, y1, x2, and y2 properties\r\n * representing endpoint coordinates.\r\n *\r\n * Returns:\r\n * {Object} An object with squared distance, along, x, and y properties.\r\n * The distance will be the shortest distance between the input point and\r\n * segment. The x and y properties represent the coordinates along the\r\n * segment where the shortest distance meets the segment. The along\r\n * attribute describes how far between the two segment points the given\r\n * point is.\r\n */\r\nOpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) {\r\n var x0 = point.x;\r\n var y0 = point.y;\r\n var x1 = segment.x1;\r\n var y1 = segment.y1;\r\n var x2 = segment.x2;\r\n var y2 = segment.y2;\r\n var dx = x2 - x1;\r\n var dy = y2 - y1;\r\n var along = (dx == 0 && dy == 0) ? 0 : ((dx * (x0 - x1)) + (dy * (y0 - y1))) /\r\n (Math.pow(dx, 2) + Math.pow(dy, 2));\r\n var x, y;\r\n if(along <= 0.0) {\r\n x = x1;\r\n y = y1;\r\n } else if(along >= 1.0) {\r\n x = x2;\r\n y = y2;\r\n } else {\r\n x = x1 + along * dx;\r\n y = y1 + along * dy;\r\n }\r\n return {\r\n distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2),\r\n x: x, y: y,\r\n along: along\r\n };\r\n};\r\n/* ======================================================================\r\n OpenLayers/Geometry/Point.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Geometry.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Geometry.Point\r\n * Point geometry class. \r\n * \r\n * Inherits from:\r\n * - \r\n */\r\nOpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, {\r\n\r\n /** \r\n * APIProperty: x \r\n * {float} \r\n */\r\n x: null,\r\n\r\n /** \r\n * APIProperty: y \r\n * {float} \r\n */\r\n y: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.Point\r\n * Construct a point geometry.\r\n *\r\n * Parameters:\r\n * x - {float} \r\n * y - {float}\r\n * \r\n */\r\n initialize: function(x, y) {\r\n OpenLayers.Geometry.prototype.initialize.apply(this, arguments);\r\n \r\n this.x = parseFloat(x);\r\n this.y = parseFloat(y);\r\n },\r\n\r\n /**\r\n * APIMethod: clone\r\n * \r\n * Returns:\r\n * {} An exact clone of this OpenLayers.Geometry.Point\r\n */\r\n clone: function(obj) {\r\n if (obj == null) {\r\n obj = new OpenLayers.Geometry.Point(this.x, this.y);\r\n }\r\n\r\n // catch any randomly tagged-on properties\r\n OpenLayers.Util.applyDefaults(obj, this);\r\n\r\n return obj;\r\n },\r\n\r\n /** \r\n * Method: calculateBounds\r\n * Create a new Bounds based on the lon/lat\r\n */\r\n calculateBounds: function () {\r\n this.bounds = new OpenLayers.Bounds(this.x, this.y,\r\n this.x, this.y);\r\n },\r\n\r\n /**\r\n * APIMethod: distanceTo\r\n * Calculate the closest distance between two geometries (on the x-y plane).\r\n *\r\n * Parameters:\r\n * geometry - {} The target geometry.\r\n * options - {Object} Optional properties for configuring the distance\r\n * calculation.\r\n *\r\n * Valid options:\r\n * details - {Boolean} Return details from the distance calculation.\r\n * Default is false.\r\n * edge - {Boolean} Calculate the distance from this geometry to the\r\n * nearest edge of the target geometry. Default is true. If true,\r\n * calling distanceTo from a geometry that is wholly contained within\r\n * the target will result in a non-zero distance. If false, whenever\r\n * geometries intersect, calling distanceTo will return 0. If false,\r\n * details cannot be returned.\r\n *\r\n * Returns:\r\n * {Number | Object} The distance between this geometry and the target.\r\n * If details is true, the return will be an object with distance,\r\n * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\r\n * the coordinates of the closest point on this geometry. The x1 and y1\r\n * properties represent the coordinates of the closest point on the\r\n * target geometry.\r\n */\r\n distanceTo: function(geometry, options) {\r\n var edge = !(options && options.edge === false);\r\n var details = edge && options && options.details;\r\n var distance, x0, y0, x1, y1, result;\r\n if(geometry instanceof OpenLayers.Geometry.Point) {\r\n x0 = this.x;\r\n y0 = this.y;\r\n x1 = geometry.x;\r\n y1 = geometry.y;\r\n distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));\r\n result = !details ?\r\n distance : {x0: x0, y0: y0, x1: x1, y1: y1, distance: distance};\r\n } else {\r\n result = geometry.distanceTo(this, options);\r\n if(details) {\r\n // switch coord order since this geom is target\r\n result = {\r\n x0: result.x1, y0: result.y1,\r\n x1: result.x0, y1: result.y0,\r\n distance: result.distance\r\n };\r\n }\r\n }\r\n return result;\r\n },\r\n \r\n /** \r\n * APIMethod: equals\r\n * Determine whether another geometry is equivalent to this one. Geometries\r\n * are considered equivalent if all components have the same coordinates.\r\n * \r\n * Parameters:\r\n * geom - {} The geometry to test. \r\n *\r\n * Returns:\r\n * {Boolean} The supplied geometry is equivalent to this geometry.\r\n */\r\n equals: function(geom) {\r\n var equals = false;\r\n if (geom != null) {\r\n equals = ((this.x == geom.x && this.y == geom.y) ||\r\n (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y)));\r\n }\r\n return equals;\r\n },\r\n \r\n /**\r\n * Method: toShortString\r\n *\r\n * Returns:\r\n * {String} Shortened String representation of Point object. \r\n * (ex. \"5, 42\")\r\n */\r\n toShortString: function() {\r\n return (this.x + \", \" + this.y);\r\n },\r\n \r\n /**\r\n * APIMethod: move\r\n * Moves a geometry by the given displacement along positive x and y axes.\r\n * This modifies the position of the geometry and clears the cached\r\n * bounds.\r\n *\r\n * Parameters:\r\n * x - {Float} Distance to move geometry in positive x direction. \r\n * y - {Float} Distance to move geometry in positive y direction.\r\n */\r\n move: function(x, y) {\r\n this.x = this.x + x;\r\n this.y = this.y + y;\r\n this.clearBounds();\r\n },\r\n\r\n /**\r\n * APIMethod: rotate\r\n * Rotate a point around another.\r\n *\r\n * Parameters:\r\n * angle - {Float} Rotation angle in degrees (measured counterclockwise\r\n * from the positive x-axis)\r\n * origin - {} Center point for the rotation\r\n */\r\n rotate: function(angle, origin) {\r\n angle *= Math.PI / 180;\r\n var radius = this.distanceTo(origin);\r\n var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x);\r\n this.x = origin.x + (radius * Math.cos(theta));\r\n this.y = origin.y + (radius * Math.sin(theta));\r\n this.clearBounds();\r\n },\r\n \r\n /**\r\n * APIMethod: getCentroid\r\n *\r\n * Returns:\r\n * {} The centroid of the collection\r\n */\r\n getCentroid: function() {\r\n return new OpenLayers.Geometry.Point(this.x, this.y);\r\n },\r\n\r\n /**\r\n * APIMethod: resize\r\n * Resize a point relative to some origin. For points, this has the effect\r\n * of scaling a vector (from the origin to the point). This method is\r\n * more useful on geometry collection subclasses.\r\n *\r\n * Parameters:\r\n * scale - {Float} Ratio of the new distance from the origin to the old\r\n * distance from the origin. A scale of 2 doubles the\r\n * distance between the point and origin.\r\n * origin - {} Point of origin for resizing\r\n * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\r\n * \r\n * Returns:\r\n * {} - The current geometry. \r\n */\r\n resize: function(scale, origin, ratio) {\r\n ratio = (ratio == undefined) ? 1 : ratio;\r\n this.x = origin.x + (scale * ratio * (this.x - origin.x));\r\n this.y = origin.y + (scale * (this.y - origin.y));\r\n this.clearBounds();\r\n return this;\r\n },\r\n \r\n /**\r\n * APIMethod: intersects\r\n * Determine if the input geometry intersects this one.\r\n *\r\n * Parameters:\r\n * geometry - {} Any type of geometry.\r\n *\r\n * Returns:\r\n * {Boolean} The input geometry intersects this one.\r\n */\r\n intersects: function(geometry) {\r\n var intersect = false;\r\n if(geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\r\n intersect = this.equals(geometry);\r\n } else {\r\n intersect = geometry.intersects(this);\r\n }\r\n return intersect;\r\n },\r\n \r\n /**\r\n * APIMethod: transform\r\n * Translate the x,y properties of the point from source to dest.\r\n * \r\n * Parameters:\r\n * source - {} \r\n * dest - {}\r\n * \r\n * Returns:\r\n * {} \r\n */\r\n transform: function(source, dest) {\r\n if ((source && dest)) {\r\n OpenLayers.Projection.transform(\r\n this, source, dest); \r\n this.bounds = null;\r\n } \r\n return this;\r\n },\r\n\r\n /**\r\n * APIMethod: getVertices\r\n * Return a list of all points in this geometry.\r\n *\r\n * Parameters:\r\n * nodes - {Boolean} For lines, only return vertices that are\r\n * endpoints. If false, for lines, only vertices that are not\r\n * endpoints will be returned. If not provided, all vertices will\r\n * be returned.\r\n *\r\n * Returns:\r\n * {Array} A list of all vertices in the geometry.\r\n */\r\n getVertices: function(nodes) {\r\n return [this];\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Geometry.Point\"\r\n});\r\n/* ======================================================================\r\n OpenLayers/Geometry/Collection.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Geometry.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Geometry.Collection\r\n * A Collection is exactly what it sounds like: A collection of different \r\n * Geometries. These are stored in the local parameter (which\r\n * can be passed as a parameter to the constructor). \r\n * \r\n * As new geometries are added to the collection, they are NOT cloned. \r\n * When removing geometries, they need to be specified by reference (ie you \r\n * have to pass in the *exact* geometry to be removed).\r\n * \r\n * The and functions here merely iterate through\r\n * the components, summing their respective areas and lengths.\r\n *\r\n * Create a new instance with the constructor.\r\n *\r\n * Inherits from:\r\n * - \r\n */\r\nOpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {\r\n\r\n /**\r\n * APIProperty: components\r\n * {Array()} The component parts of this geometry\r\n */\r\n components: null,\r\n \r\n /**\r\n * Property: componentTypes\r\n * {Array(String)} An array of class names representing the types of\r\n * components that the collection can include. A null value means the\r\n * component types are not restricted.\r\n */\r\n componentTypes: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.Collection\r\n * Creates a Geometry Collection -- a list of geoms.\r\n *\r\n * Parameters: \r\n * components - {Array()} Optional array of geometries\r\n *\r\n */\r\n initialize: function (components) {\r\n OpenLayers.Geometry.prototype.initialize.apply(this, arguments);\r\n this.components = [];\r\n if (components != null) {\r\n this.addComponents(components);\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: destroy\r\n * Destroy this geometry.\r\n */\r\n destroy: function () {\r\n this.components.length = 0;\r\n this.components = null;\r\n OpenLayers.Geometry.prototype.destroy.apply(this, arguments);\r\n },\r\n\r\n /**\r\n * APIMethod: clone\r\n * Clone this geometry.\r\n *\r\n * Returns:\r\n * {} An exact clone of this collection\r\n */\r\n clone: function() {\r\n var Constructor = OpenLayers.Util.getConstructor(this.CLASS_NAME);\r\n var geometry = new Constructor();\r\n for(var i=0, len=this.components.length; i)} An array of geometries to add\r\n */\r\n addComponents: function(components){\r\n if(!(OpenLayers.Util.isArray(components))) {\r\n components = [components];\r\n }\r\n for(var i=0, len=components.length; i} A geometry to add\r\n * index - {int} Optional index into the array to insert the component\r\n *\r\n * Returns:\r\n * {Boolean} The component geometry was successfully added\r\n */ \r\n addComponent: function(component, index) {\r\n var added = false;\r\n if(component) {\r\n if(this.componentTypes == null ||\r\n (OpenLayers.Util.indexOf(this.componentTypes,\r\n component.CLASS_NAME) > -1)) {\r\n\r\n if(index != null && (index < this.components.length)) {\r\n var components1 = this.components.slice(0, index);\r\n var components2 = this.components.slice(index, \r\n this.components.length);\r\n components1.push(component);\r\n this.components = components1.concat(components2);\r\n } else {\r\n this.components.push(component);\r\n }\r\n component.parent = this;\r\n this.clearBounds();\r\n added = true;\r\n }\r\n }\r\n return added;\r\n },\r\n \r\n /**\r\n * APIMethod: removeComponents\r\n * Remove components from this geometry.\r\n *\r\n * Parameters:\r\n * components - {Array()} The components to be removed\r\n *\r\n * Returns: \r\n * {Boolean} A component was removed.\r\n */\r\n removeComponents: function(components) {\r\n var removed = false;\r\n\r\n if(!(OpenLayers.Util.isArray(components))) {\r\n components = [components];\r\n }\r\n for(var i=components.length-1; i>=0; --i) {\r\n removed = this.removeComponent(components[i]) || removed;\r\n }\r\n return removed;\r\n },\r\n \r\n /**\r\n * Method: removeComponent\r\n * Remove a component from this geometry.\r\n *\r\n * Parameters:\r\n * component - {} \r\n *\r\n * Returns: \r\n * {Boolean} The component was removed.\r\n */\r\n removeComponent: function(component) {\r\n \r\n OpenLayers.Util.removeItem(this.components, component);\r\n \r\n // clearBounds() so that it gets recalculated on the next call\r\n // to this.getBounds();\r\n this.clearBounds();\r\n return true;\r\n },\r\n\r\n /**\r\n * APIMethod: getLength\r\n * Calculate the length of this geometry\r\n *\r\n * Returns:\r\n * {Float} The length of the geometry\r\n */\r\n getLength: function() {\r\n var length = 0.0;\r\n for (var i=0, len=this.components.length; i.\r\n *\r\n * Returns:\r\n * {Float} The area of the collection by summing its parts\r\n */\r\n getArea: function() {\r\n var area = 0.0;\r\n for (var i=0, len=this.components.length; i} The spatial reference system\r\n * for the geometry coordinates. If not provided, Geographic/WGS84 is\r\n * assumed.\r\n * \r\n * Reference:\r\n * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\r\n * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\r\n * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\r\n *\r\n * Returns:\r\n * {float} The approximate geodesic area of the geometry in square meters.\r\n */\r\n getGeodesicArea: function(projection) {\r\n var area = 0.0;\r\n for(var i=0, len=this.components.length; i} The centroid of the collection\r\n */\r\n getCentroid: function(weighted) {\r\n if (!weighted) {\r\n return this.components.length && this.components[0].getCentroid();\r\n }\r\n var len = this.components.length;\r\n if (!len) {\r\n return false;\r\n }\r\n \r\n var areas = [];\r\n var centroids = [];\r\n var areaSum = 0;\r\n var minArea = Number.MAX_VALUE;\r\n var component;\r\n for (var i=0; i 0) ? area : minArea;\r\n centroids.push(centroid);\r\n }\r\n len = areas.length;\r\n if (areaSum === 0) {\r\n // all the components in this collection have 0 area\r\n // probably a collection of points -- weight all the points the same\r\n for (var i=0; i} The spatial reference system\r\n * for the geometry coordinates. If not provided, Geographic/WGS84 is\r\n * assumed.\r\n * \r\n * Returns:\r\n * {Float} The appoximate geodesic length of the geometry in meters.\r\n */\r\n getGeodesicLength: function(projection) {\r\n var length = 0.0;\r\n for(var i=0, len=this.components.length; i} Center point for the rotation\r\n */\r\n rotate: function(angle, origin) {\r\n for(var i=0, len=this.components.length; i} Point of origin for resizing\r\n * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\r\n * \r\n * Returns:\r\n * {} - The current geometry. \r\n */\r\n resize: function(scale, origin, ratio) {\r\n for(var i=0; i} The target geometry.\r\n * options - {Object} Optional properties for configuring the distance\r\n * calculation.\r\n *\r\n * Valid options:\r\n * details - {Boolean} Return details from the distance calculation.\r\n * Default is false.\r\n * edge - {Boolean} Calculate the distance from this geometry to the\r\n * nearest edge of the target geometry. Default is true. If true,\r\n * calling distanceTo from a geometry that is wholly contained within\r\n * the target will result in a non-zero distance. If false, whenever\r\n * geometries intersect, calling distanceTo will return 0. If false,\r\n * details cannot be returned.\r\n *\r\n * Returns:\r\n * {Number | Object} The distance between this geometry and the target.\r\n * If details is true, the return will be an object with distance,\r\n * x0, y0, x1, and y1 properties. The x0 and y0 properties represent\r\n * the coordinates of the closest point on this geometry. The x1 and y1\r\n * properties represent the coordinates of the closest point on the\r\n * target geometry.\r\n */\r\n distanceTo: function(geometry, options) {\r\n var edge = !(options && options.edge === false);\r\n var details = edge && options && options.details;\r\n var result, best, distance;\r\n var min = Number.POSITIVE_INFINITY;\r\n for(var i=0, len=this.components.length; i} The geometry to test. \r\n *\r\n * Returns:\r\n * {Boolean} The supplied geometry is equivalent to this geometry.\r\n */\r\n equals: function(geometry) {\r\n var equivalent = true;\r\n if(!geometry || !geometry.CLASS_NAME ||\r\n (this.CLASS_NAME != geometry.CLASS_NAME)) {\r\n equivalent = false;\r\n } else if(!(OpenLayers.Util.isArray(geometry.components)) ||\r\n (geometry.components.length != this.components.length)) {\r\n equivalent = false;\r\n } else {\r\n for(var i=0, len=this.components.length; i} \r\n * dest - {}\r\n * \r\n * Returns:\r\n * {} \r\n */\r\n transform: function(source, dest) {\r\n if (source && dest) {\r\n for (var i=0, len=this.components.length; i} Any type of geometry.\r\n *\r\n * Returns:\r\n * {Boolean} The input geometry intersects this one.\r\n */\r\n intersects: function(geometry) {\r\n var intersect = false;\r\n for(var i=0, len=this.components.length; i constructor.\r\n *\r\n * Inherits from:\r\n * - \r\n * - \r\n */\r\nOpenLayers.Geometry.MultiPoint = OpenLayers.Class(\r\n OpenLayers.Geometry.Collection, {\r\n\r\n /**\r\n * Property: componentTypes\r\n * {Array(String)} An array of class names representing the types of\r\n * components that the collection can include. A null value means the\r\n * component types are not restricted.\r\n */\r\n componentTypes: [\"OpenLayers.Geometry.Point\"],\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.MultiPoint\r\n * Create a new MultiPoint Geometry\r\n *\r\n * Parameters:\r\n * components - {Array()} \r\n *\r\n * Returns:\r\n * {}\r\n */\r\n\r\n /**\r\n * APIMethod: addPoint\r\n * Wrapper for \r\n *\r\n * Parameters:\r\n * point - {} Point to be added\r\n * index - {Integer} Optional index\r\n */\r\n addPoint: function(point, index) {\r\n this.addComponent(point, index);\r\n },\r\n \r\n /**\r\n * APIMethod: removePoint\r\n * Wrapper for \r\n *\r\n * Parameters:\r\n * point - {} Point to be removed\r\n */\r\n removePoint: function(point){\r\n this.removeComponent(point);\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Geometry.MultiPoint\"\r\n});\r\n/* ======================================================================\r\n OpenLayers/Geometry/Curve.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Geometry/MultiPoint.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Geometry.Curve\r\n * A Curve is a MultiPoint, whose points are assumed to be connected. To \r\n * this end, we provide a \"getLength()\" function, which iterates through \r\n * the points, summing the distances between them. \r\n * \r\n * Inherits: \r\n * - \r\n */\r\nOpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, {\r\n\r\n /**\r\n * Property: componentTypes\r\n * {Array(String)} An array of class names representing the types of \r\n * components that the collection can include. A null \r\n * value means the component types are not restricted.\r\n */\r\n componentTypes: [\"OpenLayers.Geometry.Point\"],\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.Curve\r\n * \r\n * Parameters:\r\n * point - {Array()}\r\n */\r\n \r\n /**\r\n * APIMethod: getLength\r\n * \r\n * Returns:\r\n * {Float} The length of the curve\r\n */\r\n getLength: function() {\r\n var length = 0.0;\r\n if ( this.components && (this.components.length > 1)) {\r\n for(var i=1, len=this.components.length; i} The spatial reference system\r\n * for the geometry coordinates. If not provided, Geographic/WGS84 is\r\n * assumed.\r\n * \r\n * Returns:\r\n * {Float} The appoximate geodesic length of the geometry in meters.\r\n */\r\n getGeodesicLength: function(projection) {\r\n var geom = this; // so we can work with a clone if needed\r\n if(projection) {\r\n var gg = new OpenLayers.Projection(\"EPSG:4326\");\r\n if(!gg.equals(projection)) {\r\n geom = this.clone().transform(projection, gg);\r\n }\r\n }\r\n var length = 0.0;\r\n if(geom.components && (geom.components.length > 1)) {\r\n var p1, p2;\r\n for(var i=1, len=geom.components.length; i\r\n */\r\nOpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.LineString\r\n * Create a new LineString geometry\r\n *\r\n * Parameters:\r\n * points - {Array()} An array of points used to\r\n * generate the linestring\r\n *\r\n */\r\n\r\n /**\r\n * APIMethod: removeComponent\r\n * Only allows removal of a point if there are three or more points in \r\n * the linestring. (otherwise the result would be just a single point)\r\n *\r\n * Parameters: \r\n * point - {} The point to be removed\r\n *\r\n * Returns: \r\n * {Boolean} The component was removed.\r\n */\r\n removeComponent: function(point) {\r\n var removed = this.components && (this.components.length > 2);\r\n if (removed) {\r\n OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, \r\n arguments);\r\n }\r\n return removed;\r\n },\r\n \r\n /**\r\n * APIMethod: intersects\r\n * Test for instersection between two geometries. This is a cheapo\r\n * implementation of the Bently-Ottmann algorigithm. It doesn't\r\n * really keep track of a sweep line data structure. It is closer\r\n * to the brute force method, except that segments are sorted and\r\n * potential intersections are only calculated when bounding boxes\r\n * intersect.\r\n *\r\n * Parameters:\r\n * geometry - {}\r\n *\r\n * Returns:\r\n * {Boolean} The input geometry intersects this geometry.\r\n */\r\n intersects: function(geometry) {\r\n var intersect = false;\r\n var type = geometry.CLASS_NAME;\r\n if(type == \"OpenLayers.Geometry.LineString\" ||\r\n type == \"OpenLayers.Geometry.LinearRing\" ||\r\n type == \"OpenLayers.Geometry.Point\") {\r\n var segs1 = this.getSortedSegments();\r\n var segs2;\r\n if(type == \"OpenLayers.Geometry.Point\") {\r\n segs2 = [{\r\n x1: geometry.x, y1: geometry.y,\r\n x2: geometry.x, y2: geometry.y\r\n }];\r\n } else {\r\n segs2 = geometry.getSortedSegments();\r\n }\r\n var seg1, seg1x1, seg1x2, seg1y1, seg1y2,\r\n seg2, seg2y1, seg2y2;\r\n // sweep right\r\n outer: for(var i=0, len=segs1.length; i seg1x2) {\r\n // seg1 still left of seg2\r\n break;\r\n }\r\n if(seg2.x2 < seg1x1) {\r\n // seg2 still left of seg1\r\n continue;\r\n }\r\n seg2y1 = seg2.y1;\r\n seg2y2 = seg2.y2;\r\n if(Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) {\r\n // seg2 above seg1\r\n continue;\r\n }\r\n if(Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) {\r\n // seg2 below seg1\r\n continue;\r\n }\r\n if(OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) {\r\n intersect = true;\r\n break outer;\r\n }\r\n }\r\n }\r\n } else {\r\n intersect = geometry.intersects(this);\r\n }\r\n return intersect;\r\n },\r\n \r\n /**\r\n * Method: getSortedSegments\r\n *\r\n * Returns:\r\n * {Array} An array of segment objects. Segment objects have properties\r\n * x1, y1, x2, and y2. The start point is represented by x1 and y1.\r\n * The end point is represented by x2 and y2. Start and end are\r\n * ordered so that x1 < x2.\r\n */\r\n getSortedSegments: function() {\r\n var numSeg = this.components.length - 1;\r\n var segments = new Array(numSeg), point1, point2;\r\n for(var i=0; i 0) {\r\n // sort intersections along segment\r\n var xDir = seg.x1 < seg.x2 ? 1 : -1;\r\n var yDir = seg.y1 < seg.y2 ? 1 : -1;\r\n result = {\r\n lines: lines,\r\n points: intersections.sort(function(p1, p2) {\r\n return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);\r\n })\r\n };\r\n }\r\n return result;\r\n },\r\n\r\n /**\r\n * Method: split\r\n * Use this geometry (the source) to attempt to split a target geometry.\r\n * \r\n * Parameters:\r\n * target - {} The target geometry.\r\n * options - {Object} Properties of this object will be used to determine\r\n * how the split is conducted.\r\n *\r\n * Valid options:\r\n * mutual - {Boolean} Split the source geometry in addition to the target\r\n * geometry. Default is false.\r\n * edge - {Boolean} Allow splitting when only edges intersect. Default is\r\n * true. If false, a vertex on the source must be within the tolerance\r\n * distance of the intersection to be considered a split.\r\n * tolerance - {Number} If a non-null value is provided, intersections\r\n * within the tolerance distance of an existing vertex on the source\r\n * will be assumed to occur at the vertex.\r\n * \r\n * Returns:\r\n * {Array} A list of geometries (of this same type as the target) that\r\n * result from splitting the target with the source geometry. The\r\n * source and target geometry will remain unmodified. If no split\r\n * results, null will be returned. If mutual is true and a split\r\n * results, return will be an array of two arrays - the first will be\r\n * all geometries that result from splitting the source geometry and\r\n * the second will be all geometries that result from splitting the\r\n * target geometry.\r\n */\r\n split: function(target, options) {\r\n var results = null;\r\n var mutual = options && options.mutual;\r\n var sourceSplit, targetSplit, sourceParts, targetParts;\r\n if(target instanceof OpenLayers.Geometry.LineString) {\r\n var verts = this.getVertices();\r\n var vert1, vert2, seg, splits, lines, point;\r\n var points = [];\r\n sourceParts = [];\r\n for(var i=0, stop=verts.length-2; i<=stop; ++i) {\r\n vert1 = verts[i];\r\n vert2 = verts[i+1];\r\n seg = {\r\n x1: vert1.x, y1: vert1.y,\r\n x2: vert2.x, y2: vert2.y\r\n };\r\n targetParts = targetParts || [target];\r\n if(mutual) {\r\n points.push(vert1.clone());\r\n }\r\n for(var j=0; j 0) {\r\n lines.unshift(j, 1);\r\n Array.prototype.splice.apply(targetParts, lines);\r\n j += lines.length - 2;\r\n }\r\n if(mutual) {\r\n for(var k=0, len=splits.points.length; k 0 && points.length > 0) {\r\n points.push(vert2.clone());\r\n sourceParts.push(new OpenLayers.Geometry.LineString(points));\r\n }\r\n } else {\r\n results = target.splitWith(this, options);\r\n }\r\n if(targetParts && targetParts.length > 1) {\r\n targetSplit = true;\r\n } else {\r\n targetParts = [];\r\n }\r\n if(sourceParts && sourceParts.length > 1) {\r\n sourceSplit = true;\r\n } else {\r\n sourceParts = [];\r\n }\r\n if(targetSplit || sourceSplit) {\r\n if(mutual) {\r\n results = [sourceParts, targetParts];\r\n } else {\r\n results = targetParts;\r\n }\r\n }\r\n return results;\r\n },\r\n\r\n /**\r\n * Method: splitWith\r\n * Split this geometry (the target) with the given geometry (the source).\r\n *\r\n * Parameters:\r\n * geometry - {} A geometry used to split this\r\n * geometry (the source).\r\n * options - {Object} Properties of this object will be used to determine\r\n * how the split is conducted.\r\n *\r\n * Valid options:\r\n * mutual - {Boolean} Split the source geometry in addition to the target\r\n * geometry. Default is false.\r\n * edge - {Boolean} Allow splitting when only edges intersect. Default is\r\n * true. If false, a vertex on the source must be within the tolerance\r\n * distance of the intersection to be considered a split.\r\n * tolerance - {Number} If a non-null value is provided, intersections\r\n * within the tolerance distance of an existing vertex on the source\r\n * will be assumed to occur at the vertex.\r\n * \r\n * Returns:\r\n * {Array} A list of geometries (of this same type as the target) that\r\n * result from splitting the target with the source geometry. The\r\n * source and target geometry will remain unmodified. If no split\r\n * results, null will be returned. If mutual is true and a split\r\n * results, return will be an array of two arrays - the first will be\r\n * all geometries that result from splitting the source geometry and\r\n * the second will be all geometries that result from splitting the\r\n * target geometry.\r\n */\r\n splitWith: function(geometry, options) {\r\n return geometry.split(this, options);\r\n\r\n },\r\n\r\n /**\r\n * APIMethod: getVertices\r\n * Return a list of all points in this geometry.\r\n *\r\n * Parameters:\r\n * nodes - {Boolean} For lines, only return vertices that are\r\n * endpoints. If false, for lines, only vertices that are not\r\n * endpoints will be returned. If not provided, all vertices will\r\n * be returned.\r\n *\r\n * Returns:\r\n * {Array} A list of all vertices in the geometry.\r\n */\r\n getVertices: function(nodes) {\r\n var vertices;\r\n if(nodes === true) {\r\n vertices = [\r\n this.components[0],\r\n this.components[this.components.length-1]\r\n ];\r\n } else if (nodes === false) {\r\n vertices = this.components.slice(1, this.components.length-1);\r\n } else {\r\n vertices = this.components.slice();\r\n }\r\n return vertices;\r\n },\r\n\r\n /**\r\n * APIMethod: distanceTo\r\n * Calculate the closest distance between two geometries (on the x-y plane).\r\n *\r\n * Parameters:\r\n * geometry - {} The target geometry.\r\n * options - {Object} Optional properties for configuring the distance\r\n * calculation.\r\n *\r\n * Valid options:\r\n * details - {Boolean} Return details from the distance calculation.\r\n * Default is false.\r\n * edge - {Boolean} Calculate the distance from this geometry to the\r\n * nearest edge of the target geometry. Default is true. If true,\r\n * calling distanceTo from a geometry that is wholly contained within\r\n * the target will result in a non-zero distance. If false, whenever\r\n * geometries intersect, calling distanceTo will return 0. If false,\r\n * details cannot be returned.\r\n *\r\n * Returns:\r\n * {Number | Object} The distance between this geometry and the target.\r\n * If details is true, the return will be an object with distance,\r\n * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\r\n * the coordinates of the closest point on this geometry. The x1 and y1\r\n * properties represent the coordinates of the closest point on the\r\n * target geometry.\r\n */\r\n distanceTo: function(geometry, options) {\r\n var edge = !(options && options.edge === false);\r\n var details = edge && options && options.details;\r\n var result, best = {};\r\n var min = Number.POSITIVE_INFINITY;\r\n if(geometry instanceof OpenLayers.Geometry.Point) {\r\n var segs = this.getSortedSegments();\r\n var x = geometry.x;\r\n var y = geometry.y;\r\n var seg;\r\n for(var i=0, len=segs.length; i maxDistance) {\r\n maxDistance = distance;\r\n indexFarthest = index;\r\n }\r\n }\r\n \r\n if (maxDistance > tolerance && indexFarthest != firstPoint) {\r\n //Add the largest point that exceeds the tolerance\r\n pointIndexsToKeep.push(indexFarthest);\r\n douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance);\r\n douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance);\r\n }\r\n };\r\n \r\n /**\r\n * Private function calculating the perpendicular distance\r\n * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower\r\n */\r\n var perpendicularDistance = function(point1, point2, point){\r\n //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle\r\n //Base = v((x1-x2)²+(x1-x2)²) *Base of Triangle*\r\n //Area = .5*Base*H *Solve for height\r\n //Height = Area/.5/Base\r\n \r\n var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y));\r\n var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));\r\n var height = area / bottom * 2;\r\n \r\n return height;\r\n };\r\n \r\n var firstPoint = 0;\r\n var lastPoint = points.length - 1;\r\n var pointIndexsToKeep = [];\r\n \r\n //Add the first and last index to the keepers\r\n pointIndexsToKeep.push(firstPoint);\r\n pointIndexsToKeep.push(lastPoint);\r\n \r\n //The first and the last point cannot be the same\r\n while (points[firstPoint].equals(points[lastPoint])) {\r\n lastPoint--;\r\n //Addition: the first point not equal to first point in the LineString is kept as well\r\n pointIndexsToKeep.push(lastPoint);\r\n }\r\n \r\n douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance);\r\n var returnPoints = [];\r\n pointIndexsToKeep.sort(compareNumbers);\r\n for (var index = 0; index < pointIndexsToKeep.length; index++) {\r\n returnPoints.push(points[pointIndexsToKeep[index]]);\r\n }\r\n return new OpenLayers.Geometry.LineString(returnPoints);\r\n \r\n }\r\n else {\r\n return this;\r\n }\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Geometry.LineString\"\r\n});\r\n\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.LineString.geodesic\r\n *\r\n * Parameters:\r\n * interpolate - {function(number): OpenLayers.Geometry.Point} Interpolate\r\n * function.\r\n * transform - {function(OpenLayers.Geometry.Point): OpenLayers.Geometry.Point}\r\n * Transform from longitude/latitude to projected coordinates.\r\n * squaredTolerance - {number} Squared tolerance.\r\n *\r\n * Returns:\r\n * {OpenLayers.Geometry.LineString}\r\n */\r\nOpenLayers.Geometry.LineString.geodesic =\r\n function(interpolate, transform, squaredTolerance) {\r\n // FIXME reduce garbage generation\r\n // FIXME optimize stack operations\r\n\r\n var components = [];\r\n\r\n var geoA = interpolate(0);\r\n var geoB = interpolate(1);\r\n\r\n var a = transform(geoA);\r\n var b = transform(geoB);\r\n\r\n var geoStack = [geoB, geoA];\r\n var stack = [b, a];\r\n var fractionStack = [1, 0];\r\n\r\n var fractions = {};\r\n\r\n var maxIterations = 1e5;\r\n var geoM, m, fracA, fracB, fracM, key;\r\n\r\n while (--maxIterations > 0 && fractionStack.length > 0) {\r\n // Pop the a coordinate off the stack\r\n fracA = fractionStack.pop();\r\n geoA = geoStack.pop();\r\n a = stack.pop();\r\n // Add the a coordinate if it has not been added yet\r\n key = fracA.toString();\r\n if (!(key in fractions)) {\r\n components.push(a);\r\n fractions[key] = true;\r\n }\r\n // Pop the b coordinate off the stack\r\n fracB = fractionStack.pop();\r\n geoB = geoStack.pop();\r\n b = stack.pop();\r\n // Find the m point between the a and b coordinates\r\n fracM = (fracA + fracB) / 2;\r\n geoM = interpolate(fracM);\r\n m = transform(geoM);\r\n if (OpenLayers.Geometry.distanceSquaredToSegment(m, {x1: a.x, y1: a.y,\r\n x2: b.x, y2: b.y}).distance < squaredTolerance) {\r\n // If the m point is sufficiently close to the straight line, then\r\n // we discard it. Just use the b coordinate and move on to the next\r\n // line segment.\r\n components.push(b);\r\n key = fracB.toString();\r\n fractions[key] = true;\r\n } else {\r\n // Otherwise, we need to subdivide the current line segment.\r\n // Split it into two and push the two line segments onto the stack.\r\n fractionStack.push(fracB, fracM, fracM, fracA);\r\n stack.push(b, m, m, a);\r\n geoStack.push(geoB, geoM, geoM, geoA);\r\n }\r\n }\r\n\r\n return new OpenLayers.Geometry.LineString(components);\r\n};\r\n\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.LineString.geodesicMeridian\r\n * Generate a meridian (line at constant longitude).\r\n *\r\n * Parameters:\r\n * lon - {number} Longitude.\r\n * lat1 - {number} Latitude 1.\r\n * lat2 - {number} Latitude 2.\r\n * projection - {OpenLayers.Projection} Projection.\r\n * squaredTolerance - {number} Squared tolerance.\r\n *\r\n * Returns:\r\n * {OpenLayers.Geometry.LineString} Line geometry for the meridian at .\r\n */\r\nOpenLayers.Geometry.LineString.geodesicMeridian =\r\n function(lon, lat1, lat2, projection, squaredTolerance) {\r\n var epsg4326Projection = new OpenLayers.Projection('EPSG:4326');\r\n return OpenLayers.Geometry.LineString.geodesic(\r\n function(frac) {\r\n return new OpenLayers.Geometry.Point(\r\n lon, lat1 + ((lat2 - lat1) * frac));\r\n },\r\n function(point) {\r\n return point.transform(epsg4326Projection, projection);\r\n },\r\n squaredTolerance\r\n );\r\n};\r\n\r\n\r\n/**\r\n * Function: OpenLayers.Geometry.LineString.geodesicParallel\r\n * Generate a parallel (line at constant latitude).\r\n *\r\n * Parameters:\r\n * lat - {number} Latitude.\r\n * lon1 - {number} Longitude 1.\r\n * lon2 - {number} Longitude 2.\r\n * projection {OpenLayers.Projection} Projection.\r\n * squaredTolerance - {number} Squared tolerance.\r\n *\r\n * Returns:\r\n * {OpenLayers.Geometry.LineString} Line geometry for the parallel at .\r\n */\r\nOpenLayers.Geometry.LineString.geodesicParallel =\r\n function(lat, lon1, lon2, projection, squaredTolerance) {\r\n var epsg4326Projection = new OpenLayers.Projection('EPSG:4326');\r\n return OpenLayers.Geometry.LineString.geodesic(\r\n function(frac) {\r\n return new OpenLayers.Geometry.Point(\r\n lon1 + ((lon2 - lon1) * frac), lat);\r\n },\r\n function(point) {\r\n return point.transform(epsg4326Projection, projection);\r\n },\r\n squaredTolerance\r\n );\r\n};\r\n\r\n/* ======================================================================\r\n OpenLayers/Geometry/LinearRing.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/Geometry/LineString.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Geometry.LinearRing\r\n * \r\n * A Linear Ring is a special LineString which is closed. It closes itself \r\n * automatically on every addPoint/removePoint by adding a copy of the first\r\n * point as the last point. \r\n * \r\n * Also, as it is the first in the line family to close itself, a getArea()\r\n * function is defined to calculate the enclosed area of the linearRing\r\n * \r\n * Inherits:\r\n * - \r\n */\r\nOpenLayers.Geometry.LinearRing = OpenLayers.Class(\r\n OpenLayers.Geometry.LineString, {\r\n\r\n /**\r\n * Property: componentTypes\r\n * {Array(String)} An array of class names representing the types of \r\n * components that the collection can include. A null \r\n * value means the component types are not restricted.\r\n */\r\n componentTypes: [\"OpenLayers.Geometry.Point\"],\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.LinearRing\r\n * Linear rings are constructed with an array of points. This array\r\n * can represent a closed or open ring. If the ring is open (the last\r\n * point does not equal the first point), the constructor will close\r\n * the ring. If the ring is already closed (the last point does equal\r\n * the first point), it will be left closed.\r\n * \r\n * Parameters:\r\n * points - {Array()} points\r\n */\r\n\r\n /**\r\n * APIMethod: addComponent\r\n * Adds a point to geometry components. If the point is to be added to\r\n * the end of the components array and it is the same as the last point\r\n * already in that array, the duplicate point is not added. This has \r\n * the effect of closing the ring if it is not already closed, and \r\n * doing the right thing if it is already closed. This behavior can \r\n * be overridden by calling the method with a non-null index as the \r\n * second argument.\r\n *\r\n * Parameters:\r\n * point - {}\r\n * index - {Integer} Index into the array to insert the component\r\n * \r\n * Returns:\r\n * {Boolean} Was the Point successfully added?\r\n */\r\n addComponent: function(point, index) {\r\n var added = false;\r\n\r\n //remove last point\r\n var lastPoint = this.components.pop();\r\n\r\n // given an index, add the point\r\n // without an index only add non-duplicate points\r\n if(index != null || !point.equals(lastPoint)) {\r\n added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, \r\n arguments);\r\n }\r\n\r\n //append copy of first point\r\n var firstPoint = this.components[0];\r\n OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, \r\n [firstPoint]);\r\n \r\n return added;\r\n },\r\n \r\n /**\r\n * APIMethod: removeComponent\r\n * Removes a point from geometry components.\r\n *\r\n * Parameters:\r\n * point - {}\r\n *\r\n * Returns: \r\n * {Boolean} The component was removed.\r\n */\r\n removeComponent: function(point) {\r\n var removed = this.components && (this.components.length > 3);\r\n if (removed) {\r\n //remove last point\r\n this.components.pop();\r\n \r\n //remove our point\r\n OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, \r\n arguments);\r\n //append copy of first point\r\n var firstPoint = this.components[0];\r\n OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, \r\n [firstPoint]);\r\n }\r\n return removed;\r\n },\r\n \r\n /**\r\n * APIMethod: move\r\n * Moves a geometry by the given displacement along positive x and y axes.\r\n * This modifies the position of the geometry and clears the cached\r\n * bounds.\r\n *\r\n * Parameters:\r\n * x - {Float} Distance to move geometry in positive x direction. \r\n * y - {Float} Distance to move geometry in positive y direction.\r\n */\r\n move: function(x, y) {\r\n for(var i = 0, len=this.components.length; i} Center point for the rotation\r\n */\r\n rotate: function(angle, origin) {\r\n for(var i=0, len=this.components.length; i} Point of origin for resizing\r\n * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\r\n * \r\n * Returns:\r\n * {} - The current geometry. \r\n */\r\n resize: function(scale, origin, ratio) {\r\n for(var i=0, len=this.components.length; i}\r\n * dest - {}\r\n * \r\n * Returns:\r\n * {} \r\n */\r\n transform: function(source, dest) {\r\n if (source && dest) {\r\n for (var i=0, len=this.components.length; i} The centroid of the collection\r\n */\r\n getCentroid: function() {\r\n if (this.components) {\r\n var len = this.components.length;\r\n if (len > 0 && len <= 2) {\r\n return this.components[0].clone();\r\n } else if (len > 2) {\r\n var sumX = 0.0;\r\n var sumY = 0.0;\r\n var x0 = this.components[0].x;\r\n var y0 = this.components[0].y;\r\n var area = -1 * this.getArea();\r\n if (area != 0) {\r\n for (var i = 0; i < len - 1; i++) {\r\n var b = this.components[i];\r\n var c = this.components[i+1];\r\n sumX += (b.x + c.x - 2 * x0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));\r\n sumY += (b.y + c.y - 2 * y0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));\r\n }\r\n var x = x0 + sumX / (6 * area);\r\n var y = y0 + sumY / (6 * area);\r\n } else {\r\n for (var i = 0; i < len - 1; i++) {\r\n sumX += this.components[i].x;\r\n sumY += this.components[i].y;\r\n }\r\n var x = sumX / (len - 1);\r\n var y = sumY / (len - 1);\r\n }\r\n return new OpenLayers.Geometry.Point(x, y);\r\n } else {\r\n return null;\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: getArea\r\n * Note - The area is positive if the ring is oriented CW, otherwise\r\n * it will be negative.\r\n * \r\n * Returns:\r\n * {Float} The signed area for a ring.\r\n */\r\n getArea: function() {\r\n var area = 0.0;\r\n if ( this.components && (this.components.length > 2)) {\r\n var sum = 0.0;\r\n for (var i=0, len=this.components.length; i} The spatial reference system\r\n * for the geometry coordinates. If not provided, Geographic/WGS84 is\r\n * assumed.\r\n * \r\n * Reference:\r\n * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\r\n * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\r\n * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\r\n *\r\n * Returns:\r\n * {float} The approximate signed geodesic area of the polygon in square\r\n * meters.\r\n */\r\n getGeodesicArea: function(projection) {\r\n var ring = this; // so we can work with a clone if needed\r\n if(projection) {\r\n var gg = new OpenLayers.Projection(\"EPSG:4326\");\r\n if(!gg.equals(projection)) {\r\n ring = this.clone().transform(projection, gg);\r\n }\r\n }\r\n var area = 0.0;\r\n var len = ring.components && ring.components.length;\r\n if(len > 2) {\r\n var p1, p2;\r\n for(var i=0; i}\r\n *\r\n * Returns:\r\n * {Boolean | Number} The point is inside the linear ring. Returns 1 if\r\n * the point is coincident with an edge. Returns boolean otherwise.\r\n */\r\n containsPoint: function(point) {\r\n var approx = OpenLayers.Number.limitSigDigs;\r\n var digs = 14;\r\n var px = approx(point.x, digs);\r\n var py = approx(point.y, digs);\r\n function getX(y, x1, y1, x2, y2) {\r\n return (y - y2) * ((x2 - x1) / (y2 - y1)) + x2;\r\n }\r\n var numSeg = this.components.length - 1;\r\n var start, end, x1, y1, x2, y2, cx, cy;\r\n var crosses = 0;\r\n for(var i=0; i= x1 && px <= x2) || // right or vert\r\n x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert\r\n // point on edge\r\n crosses = -1;\r\n break;\r\n }\r\n }\r\n // ignore other horizontal edges\r\n continue;\r\n }\r\n cx = approx(getX(py, x1, y1, x2, y2), digs);\r\n if(cx == px) {\r\n // point on line\r\n if(y1 < y2 && (py >= y1 && py <= y2) || // upward\r\n y1 > y2 && (py <= y1 && py >= y2)) { // downward\r\n // point on edge\r\n crosses = -1;\r\n break;\r\n }\r\n }\r\n if(cx <= px) {\r\n // no crossing to the right\r\n continue;\r\n }\r\n if(x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {\r\n // no crossing\r\n continue;\r\n }\r\n if(y1 < y2 && (py >= y1 && py < y2) || // upward\r\n y1 > y2 && (py < y1 && py >= y2)) { // downward\r\n ++crosses;\r\n }\r\n }\r\n var contained = (crosses == -1) ?\r\n // on edge\r\n 1 :\r\n // even (out) or odd (in)\r\n !!(crosses & 1);\r\n\r\n return contained;\r\n },\r\n\r\n /**\r\n * APIMethod: intersects\r\n * Determine if the input geometry intersects this one.\r\n *\r\n * Parameters:\r\n * geometry - {} Any type of geometry.\r\n *\r\n * Returns:\r\n * {Boolean} The input geometry intersects this one.\r\n */\r\n intersects: function(geometry) {\r\n var intersect = false;\r\n if(geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\r\n intersect = this.containsPoint(geometry);\r\n } else if(geometry.CLASS_NAME == \"OpenLayers.Geometry.LineString\") {\r\n intersect = geometry.intersects(this);\r\n } else if(geometry.CLASS_NAME == \"OpenLayers.Geometry.LinearRing\") {\r\n intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply(\r\n this, [geometry]\r\n );\r\n } else {\r\n // check for component intersections\r\n for(var i=0, len=geometry.components.length; i \r\n * - \r\n */\r\nOpenLayers.Geometry.Polygon = OpenLayers.Class(\r\n OpenLayers.Geometry.Collection, {\r\n\r\n /**\r\n * Property: componentTypes\r\n * {Array(String)} An array of class names representing the types of\r\n * components that the collection can include. A null value means the\r\n * component types are not restricted.\r\n */\r\n componentTypes: [\"OpenLayers.Geometry.LinearRing\"],\r\n\r\n /**\r\n * Constructor: OpenLayers.Geometry.Polygon\r\n * Constructor for a Polygon geometry. \r\n * The first ring (this.component[0])is the outer bounds of the polygon and \r\n * all subsequent rings (this.component[1-n]) are internal holes.\r\n *\r\n *\r\n * Parameters:\r\n * components - {Array()} \r\n */\r\n\r\n /** \r\n * APIMethod: getArea\r\n * Calculated by subtracting the areas of the internal holes from the \r\n * area of the outer hole.\r\n * \r\n * Returns:\r\n * {float} The area of the geometry\r\n */\r\n getArea: function() {\r\n var area = 0.0;\r\n if ( this.components && (this.components.length > 0)) {\r\n area += Math.abs(this.components[0].getArea());\r\n for (var i=1, len=this.components.length; i} The spatial reference system\r\n * for the geometry coordinates. If not provided, Geographic/WGS84 is\r\n * assumed.\r\n * \r\n * Reference:\r\n * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\r\n * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\r\n * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\r\n *\r\n * Returns:\r\n * {float} The approximate geodesic area of the polygon in square meters.\r\n */\r\n getGeodesicArea: function(projection) {\r\n var area = 0.0;\r\n if(this.components && (this.components.length > 0)) {\r\n area += Math.abs(this.components[0].getGeodesicArea(projection));\r\n for(var i=1, len=this.components.length; i}\r\n *\r\n * Returns:\r\n * {Boolean | Number} The point is inside the polygon. Returns 1 if the\r\n * point is on an edge. Returns boolean otherwise.\r\n */\r\n containsPoint: function(point) {\r\n var numRings = this.components.length;\r\n var contained = false;\r\n if(numRings > 0) {\r\n // check exterior ring - 1 means on edge, boolean otherwise\r\n contained = this.components[0].containsPoint(point);\r\n if(contained !== 1) {\r\n if(contained && numRings > 1) {\r\n // check interior rings\r\n var hole;\r\n for(var i=1; i} Any type of geometry.\r\n *\r\n * Returns:\r\n * {Boolean} The input geometry intersects this one.\r\n */\r\n intersects: function(geometry) {\r\n var intersect = false;\r\n var i, len;\r\n if(geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\r\n intersect = this.containsPoint(geometry);\r\n } else if(geometry.CLASS_NAME == \"OpenLayers.Geometry.LineString\" ||\r\n geometry.CLASS_NAME == \"OpenLayers.Geometry.LinearRing\") {\r\n // check if rings/linestrings intersect\r\n for(i=0, len=this.components.length; i} The target geometry.\r\n * options - {Object} Optional properties for configuring the distance\r\n * calculation.\r\n *\r\n * Valid options:\r\n * details - {Boolean} Return details from the distance calculation.\r\n * Default is false.\r\n * edge - {Boolean} Calculate the distance from this geometry to the\r\n * nearest edge of the target geometry. Default is true. If true,\r\n * calling distanceTo from a geometry that is wholly contained within\r\n * the target will result in a non-zero distance. If false, whenever\r\n * geometries intersect, calling distanceTo will return 0. If false,\r\n * details cannot be returned.\r\n *\r\n * Returns:\r\n * {Number | Object} The distance between this geometry and the target.\r\n * If details is true, the return will be an object with distance,\r\n * x0, y0, x1, and y1 properties. The x0 and y0 properties represent\r\n * the coordinates of the closest point on this geometry. The x1 and y1\r\n * properties represent the coordinates of the closest point on the\r\n * target geometry.\r\n */\r\n distanceTo: function(geometry, options) {\r\n var edge = !(options && options.edge === false);\r\n var result;\r\n // this is the case where we might not be looking for distance to edge\r\n if(!edge && this.intersects(geometry)) {\r\n result = 0;\r\n } else {\r\n result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(\r\n this, [geometry, options]\r\n );\r\n }\r\n return result;\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Geometry.Polygon\"\r\n});\r\n\r\n/**\r\n * APIMethod: createRegularPolygon\r\n * Create a regular polygon around a radius. Useful for creating circles \r\n * and the like.\r\n *\r\n * Parameters:\r\n * origin - {} center of polygon.\r\n * radius - {Float} distance to vertex, in map units.\r\n * sides - {Integer} Number of sides. 20 approximates a circle.\r\n * rotation - {Float} original angle of rotation, in degrees.\r\n */\r\nOpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) { \r\n var angle = Math.PI * ((1/sides) - (1/2));\r\n if(rotation) {\r\n angle += (rotation / 180) * Math.PI;\r\n }\r\n var rotatedAngle, x, y;\r\n var points = [];\r\n for(var i=0; i 1;\r\n },\r\n\r\n /**\r\n * Method: isTouchEvent\r\n * Determine whether the event was triggered by a touch\r\n * \r\n * Parameters:\r\n * evt - {Event}\r\n * \r\n * Returns:\r\n * {Boolean}\r\n */\r\n isTouchEvent: function(evt) {\r\n return (\"\" + evt.type).indexOf(\"touch\") === 0 || (\r\n \"pointerType\" in evt && (\r\n evt.pointerType === evt.MSPOINTER_TYPE_TOUCH /*IE10 pointer*/ ||\r\n evt.pointerType === \"touch\" /*W3C pointer*/));\r\n },\r\n\r\n /**\r\n * Method: isLeftClick\r\n * Determine whether event was caused by a left click. \r\n *\r\n * Parameters:\r\n * event - {Event} \r\n * \r\n * Returns:\r\n * {Boolean}\r\n */\r\n isLeftClick: function(event) {\r\n return (((event.which) && (event.which == 1)) ||\r\n ((event.button) && (event.button == 1)));\r\n },\r\n\r\n /**\r\n * Method: isRightClick\r\n * Determine whether event was caused by a right mouse click. \r\n *\r\n * Parameters:\r\n * event - {Event} \r\n * \r\n * Returns:\r\n * {Boolean}\r\n */\r\n isRightClick: function(event) {\r\n return (((event.which) && (event.which == 3)) ||\r\n ((event.button) && (event.button == 2)));\r\n },\r\n \r\n /**\r\n * Method: stop\r\n * Stops an event from propagating. \r\n *\r\n * Parameters: \r\n * event - {Event} \r\n * allowDefault - {Boolean} If true, we stop the event chain but \r\n * still allow the default browser behaviour (text selection,\r\n * radio-button clicking, etc). Default is false.\r\n */\r\n stop: function(event, allowDefault) {\r\n \r\n if (!allowDefault) { \r\n OpenLayers.Event.preventDefault(event);\r\n }\r\n \r\n if (event.stopPropagation) {\r\n event.stopPropagation();\r\n } else {\r\n event.cancelBubble = true;\r\n }\r\n },\r\n\r\n /**\r\n * Method: preventDefault\r\n * Cancels the event if it is cancelable, without stopping further\r\n * propagation of the event.\r\n *\r\n * Parameters:\r\n * event - {Event}\r\n */\r\n preventDefault: function(event) {\r\n if (event.preventDefault) {\r\n event.preventDefault();\r\n } else {\r\n event.returnValue = false;\r\n }\r\n },\r\n\r\n /** \r\n * Method: findElement\r\n * \r\n * Parameters:\r\n * event - {Event} \r\n * tagName - {String} \r\n * \r\n * Returns:\r\n * {DOMElement} The first node with the given tagName, starting from the\r\n * node the event was triggered on and traversing the DOM upwards\r\n */\r\n findElement: function(event, tagName) {\r\n var element = OpenLayers.Event.element(event);\r\n while (element.parentNode && (!element.tagName ||\r\n (element.tagName.toUpperCase() != tagName.toUpperCase()))){\r\n element = element.parentNode;\r\n }\r\n return element;\r\n },\r\n\r\n /** \r\n * Method: observe\r\n * \r\n * Parameters:\r\n * elementParam - {DOMElement || String} \r\n * name - {String} \r\n * observer - {function} \r\n * useCapture - {Boolean} \r\n */\r\n observe: function(elementParam, name, observer, useCapture) {\r\n var element = OpenLayers.Util.getElement(elementParam);\r\n useCapture = useCapture || false;\r\n\r\n if (name == 'keypress' &&\r\n (navigator.appVersion.match(/Konqueror|Safari|KHTML/)\r\n || element.attachEvent)) {\r\n name = 'keydown';\r\n }\r\n\r\n //if observers cache has not yet been created, create it\r\n if (!this.observers) {\r\n this.observers = {};\r\n }\r\n\r\n //if not already assigned, make a new unique cache ID\r\n if (!element._eventCacheID) {\r\n var idPrefix = \"eventCacheID_\";\r\n if (element.id) {\r\n idPrefix = element.id + \"_\" + idPrefix;\r\n }\r\n element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);\r\n }\r\n\r\n var cacheID = element._eventCacheID;\r\n\r\n //if there is not yet a hash entry for this element, add one\r\n if (!this.observers[cacheID]) {\r\n this.observers[cacheID] = [];\r\n }\r\n\r\n //add a new observer to this element's list\r\n this.observers[cacheID].push({\r\n 'element': element,\r\n 'name': name,\r\n 'observer': observer,\r\n 'useCapture': useCapture\r\n });\r\n\r\n //add the actual browser event listener\r\n if (element.addEventListener) {\r\n element.addEventListener(name, observer, useCapture);\r\n } else if (element.attachEvent) {\r\n element.attachEvent('on' + name, observer);\r\n }\r\n },\r\n\r\n /** \r\n * Method: stopObservingElement\r\n * Given the id of an element to stop observing, cycle through the \r\n * element's cached observers, calling stopObserving on each one, \r\n * skipping those entries which can no longer be removed.\r\n * \r\n * parameters:\r\n * elementParam - {DOMElement || String} \r\n */\r\n stopObservingElement: function(elementParam) {\r\n var element = OpenLayers.Util.getElement(elementParam);\r\n var cacheID = element._eventCacheID;\r\n\r\n this._removeElementObservers(OpenLayers.Event.observers[cacheID]);\r\n },\r\n\r\n /**\r\n * Method: _removeElementObservers\r\n *\r\n * Parameters:\r\n * elementObservers - {Array(Object)} Array of (element, name, \r\n * observer, usecapture) objects, \r\n * taken directly from hashtable\r\n */\r\n _removeElementObservers: function(elementObservers) {\r\n if (elementObservers) {\r\n for(var i = elementObservers.length-1; i >= 0; i--) {\r\n var entry = elementObservers[i];\r\n OpenLayers.Event.stopObserving.apply(this, [\r\n entry.element, entry.name, entry.observer, entry.useCapture\r\n ]);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * Method: stopObserving\r\n * \r\n * Parameters:\r\n * elementParam - {DOMElement || String} \r\n * name - {String} \r\n * observer - {function} \r\n * useCapture - {Boolean} \r\n * \r\n * Returns:\r\n * {Boolean} Whether or not the event observer was removed\r\n */\r\n stopObserving: function(elementParam, name, observer, useCapture) {\r\n useCapture = useCapture || false;\r\n \r\n var element = OpenLayers.Util.getElement(elementParam);\r\n var cacheID = element._eventCacheID;\r\n\r\n if (name == 'keypress') {\r\n if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || \r\n element.detachEvent) {\r\n name = 'keydown';\r\n }\r\n }\r\n\r\n // find element's entry in this.observers cache and remove it\r\n var foundEntry = false;\r\n var elementObservers = OpenLayers.Event.observers[cacheID];\r\n if (elementObservers) {\r\n \r\n // find the specific event type in the element's list\r\n var i=0;\r\n while(!foundEntry && i < elementObservers.length) {\r\n var cacheEntry = elementObservers[i];\r\n \r\n if ((cacheEntry.name == name) &&\r\n (cacheEntry.observer == observer) &&\r\n (cacheEntry.useCapture == useCapture)) {\r\n \r\n elementObservers.splice(i, 1);\r\n if (elementObservers.length == 0) {\r\n delete OpenLayers.Event.observers[cacheID];\r\n }\r\n foundEntry = true;\r\n break; \r\n }\r\n i++; \r\n }\r\n }\r\n \r\n //actually remove the event listener from browser\r\n if (foundEntry) {\r\n if (element.removeEventListener) {\r\n element.removeEventListener(name, observer, useCapture);\r\n } else if (element && element.detachEvent) {\r\n element.detachEvent('on' + name, observer);\r\n }\r\n }\r\n return foundEntry;\r\n },\r\n \r\n /** \r\n * Method: unloadCache\r\n * Cycle through all the element entries in the events cache and call\r\n * stopObservingElement on each. \r\n */\r\n unloadCache: function() {\r\n // check for OpenLayers.Event before checking for observers, because\r\n // OpenLayers.Event may be undefined in IE if no map instance was\r\n // created\r\n if (OpenLayers.Event && OpenLayers.Event.observers) {\r\n for (var cacheID in OpenLayers.Event.observers) {\r\n var elementObservers = OpenLayers.Event.observers[cacheID];\r\n OpenLayers.Event._removeElementObservers.apply(this, \r\n [elementObservers]);\r\n }\r\n OpenLayers.Event.observers = false;\r\n }\r\n },\r\n\r\n CLASS_NAME: \"OpenLayers.Event\"\r\n};\r\n\r\n/* prevent memory leaks in IE */\r\nOpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);\r\n\r\n/**\r\n * Class: OpenLayers.Events\r\n */\r\nOpenLayers.Events = OpenLayers.Class({\r\n\r\n /** \r\n * Constant: BROWSER_EVENTS\r\n * {Array(String)} supported events \r\n */\r\n BROWSER_EVENTS: [\r\n \"mouseover\", \"mouseout\",\r\n \"mousedown\", \"mouseup\", \"mousemove\", \r\n \"click\", \"dblclick\", \"rightclick\", \"dblrightclick\",\r\n \"resize\", \"focus\", \"blur\",\r\n \"touchstart\", \"touchmove\", \"touchend\",\r\n \"keydown\"\r\n ],\r\n \r\n /**\r\n * Constant: standard pointer model\r\n * {string}\r\n */\r\n TOUCH_MODEL_POINTER: \"pointer\",\r\n\r\n /**\r\n * Constant: prefixed pointer model (IE10)\r\n * {string}\r\n */\r\n TOUCH_MODEL_MSPOINTER: \"MSPointer\",\r\n\r\n /**\r\n * Constant: legacy touch model\r\n * {string}\r\n */\r\n TOUCH_MODEL_TOUCH: \"touch\",\r\n\r\n /** \r\n * Property: listeners \r\n * {Object} Hashtable of Array(Function): events listener functions \r\n */\r\n listeners: null,\r\n\r\n /** \r\n * Property: object \r\n * {Object} the code object issuing application events \r\n */\r\n object: null,\r\n\r\n /** \r\n * Property: element \r\n * {DOMElement} the DOM element receiving browser events \r\n */\r\n element: null,\r\n\r\n /** \r\n * Property: eventHandler \r\n * {Function} bound event handler attached to elements \r\n */\r\n eventHandler: null,\r\n\r\n /** \r\n * APIProperty: fallThrough \r\n * {Boolean} \r\n */\r\n fallThrough: null,\r\n\r\n /** \r\n * APIProperty: includeXY\r\n * {Boolean} Should the .xy property automatically be created for browser\r\n * mouse events? In general, this should be false. If it is true, then\r\n * mouse events will automatically generate a '.xy' property on the \r\n * event object that is passed. (Prior to OpenLayers 2.7, this was true\r\n * by default.) Otherwise, you can call the getMousePosition on the\r\n * relevant events handler on the object available via the 'evt.object'\r\n * property of the evt object. So, for most events, you can call:\r\n * function named(evt) { \r\n * this.xy = this.object.events.getMousePosition(evt) \r\n * } \r\n *\r\n * This option typically defaults to false for performance reasons:\r\n * when creating an events object whose primary purpose is to manage\r\n * relatively positioned mouse events within a div, it may make\r\n * sense to set it to true.\r\n *\r\n * This option is also used to control whether the events object caches\r\n * offsets. If this is false, it will not: the reason for this is that\r\n * it is only expected to be called many times if the includeXY property\r\n * is set to true. If you set this to true, you are expected to clear \r\n * the offset cache manually (using this.clearMouseCache()) if:\r\n * the border of the element changes\r\n * the location of the element in the page changes\r\n */\r\n includeXY: false, \r\n \r\n /**\r\n * APIProperty: extensions\r\n * {Object} Event extensions registered with this instance. Keys are\r\n * event types, values are {OpenLayers.Events.*} extension instances or\r\n * {Boolean} for events that an instantiated extension provides in\r\n * addition to the one it was created for.\r\n *\r\n * Extensions create an event in addition to browser events, which usually\r\n * fires when a sequence of browser events is completed. Extensions are\r\n * automatically instantiated when a listener is registered for an event\r\n * provided by an extension.\r\n *\r\n * Extensions are created in the namespace using\r\n * , and named after the event they provide.\r\n * The constructor receives the target instance as\r\n * argument. Extensions that need to capture browser events before they\r\n * propagate can register their listeners events using , with\r\n * {extension: true} as 4th argument.\r\n *\r\n * If an extension creates more than one event, an alias for each event\r\n * type should be created and reference the same class. The constructor\r\n * should set a reference in the target's extensions registry to itself.\r\n *\r\n * Below is a minimal extension that provides the \"foostart\" and \"fooend\"\r\n * event types, which replace the native \"click\" event type if clicked on\r\n * an element with the css class \"foo\":\r\n *\r\n * (code)\r\n * OpenLayers.Events.foostart = OpenLayers.Class({\r\n * initialize: function(target) {\r\n * this.target = target;\r\n * this.target.register(\"click\", this, this.doStuff, {extension: true});\r\n * // only required if extension provides more than one event type\r\n * this.target.extensions[\"foostart\"] = true;\r\n * this.target.extensions[\"fooend\"] = true;\r\n * },\r\n * destroy: function() {\r\n * var target = this.target;\r\n * target.unregister(\"click\", this, this.doStuff);\r\n * delete this.target;\r\n * // only required if extension provides more than one event type\r\n * delete target.extensions[\"foostart\"];\r\n * delete target.extensions[\"fooend\"];\r\n * },\r\n * doStuff: function(evt) {\r\n * var propagate = true;\r\n * if (OpenLayers.Event.element(evt).className === \"foo\") {\r\n * propagate = false;\r\n * var target = this.target;\r\n * target.triggerEvent(\"foostart\");\r\n * window.setTimeout(function() {\r\n * target.triggerEvent(\"fooend\");\r\n * }, 1000);\r\n * }\r\n * return propagate;\r\n * }\r\n * });\r\n * // only required if extension provides more than one event type\r\n * OpenLayers.Events.fooend = OpenLayers.Events.foostart;\r\n * (end)\r\n * \r\n */\r\n extensions: null,\r\n \r\n /**\r\n * Property: extensionCount\r\n * {Object} Keys are event types (like in ), values are the\r\n * number of extension listeners for each event type.\r\n */\r\n extensionCount: null,\r\n\r\n /**\r\n * Method: clearMouseListener\r\n * A version of that is bound to this instance so that\r\n * it can be used with and\r\n * .\r\n */\r\n clearMouseListener: null,\r\n\r\n /**\r\n * Constructor: OpenLayers.Events\r\n * Construct an OpenLayers.Events object.\r\n *\r\n * Parameters:\r\n * object - {Object} The js object to which this Events object is being added\r\n * element - {DOMElement} A dom element to respond to browser events\r\n * eventTypes - {Array(String)} Deprecated. Array of custom application\r\n * events. A listener may be registered for any named event, regardless\r\n * of the values provided here.\r\n * fallThrough - {Boolean} Allow events to fall through after these have\r\n * been handled?\r\n * options - {Object} Options for the events object.\r\n */\r\n initialize: function (object, element, eventTypes, fallThrough, options) {\r\n OpenLayers.Util.extend(this, options);\r\n this.object = object;\r\n this.fallThrough = fallThrough;\r\n this.listeners = {};\r\n this.extensions = {};\r\n this.extensionCount = {};\r\n this._pointerTouches = [];\r\n \r\n // if a dom element is specified, add a listeners list \r\n // for browser events on the element and register them\r\n if (element != null) {\r\n this.attachToElement(element);\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: destroy\r\n */\r\n destroy: function () {\r\n for (var e in this.extensions) {\r\n if (typeof this.extensions[e] !== \"boolean\") {\r\n this.extensions[e].destroy();\r\n }\r\n }\r\n this.extensions = null;\r\n if (this.element) {\r\n OpenLayers.Event.stopObservingElement(this.element);\r\n if(this.element.hasScrollEvent) {\r\n OpenLayers.Event.stopObserving(\r\n window, \"scroll\", this.clearMouseListener\r\n );\r\n }\r\n }\r\n this.element = null;\r\n\r\n this.listeners = null;\r\n this.object = null;\r\n this.fallThrough = null;\r\n this.eventHandler = null;\r\n },\r\n\r\n /**\r\n * APIMethod: addEventType\r\n * Deprecated. Any event can be triggered without adding it first.\r\n * \r\n * Parameters:\r\n * eventName - {String}\r\n */\r\n addEventType: function(eventName) {\r\n },\r\n\r\n /**\r\n * Method: attachToElement\r\n *\r\n * Parameters:\r\n * element - {HTMLDOMElement} a DOM element to attach browser events to\r\n */\r\n attachToElement: function (element) {\r\n if (this.element) {\r\n OpenLayers.Event.stopObservingElement(this.element);\r\n } else {\r\n // keep a bound copy of handleBrowserEvent() so that we can\r\n // pass the same function to both Event.observe() and .stopObserving()\r\n this.eventHandler = OpenLayers.Function.bindAsEventListener(\r\n this.handleBrowserEvent, this\r\n );\r\n \r\n // to be used with observe and stopObserving\r\n this.clearMouseListener = OpenLayers.Function.bind(\r\n this.clearMouseCache, this\r\n );\r\n }\r\n this.element = element;\r\n var touchModel = this.getTouchModel();\r\n var type;\r\n for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {\r\n type = this.BROWSER_EVENTS[i];\r\n // register the event cross-browser\r\n OpenLayers.Event.observe(element, type, this.eventHandler\r\n );\r\n if ((touchModel === this.TOUCH_MODEL_POINTER ||\r\n touchModel === this.TOUCH_MODEL_MSPOINTER) &&\r\n type.indexOf('touch') === 0) {\r\n this.addPointerTouchListener(element, type, this.eventHandler);\r\n }\r\n }\r\n // disable dragstart in IE so that mousedown/move/up works normally\r\n OpenLayers.Event.observe(element, \"dragstart\", OpenLayers.Event.stop);\r\n },\r\n \r\n /**\r\n * APIMethod: on\r\n * Convenience method for registering listeners with a common scope.\r\n * Internally, this method calls as shown in the examples\r\n * below.\r\n *\r\n * Example use:\r\n * (code)\r\n * // register a single listener for the \"loadstart\" event\r\n * events.on({\"loadstart\": loadStartListener});\r\n *\r\n * // this is equivalent to the following\r\n * events.register(\"loadstart\", undefined, loadStartListener);\r\n *\r\n * // register multiple listeners to be called with the same `this` object\r\n * events.on({\r\n * \"loadstart\": loadStartListener,\r\n * \"loadend\": loadEndListener,\r\n * scope: object\r\n * });\r\n *\r\n * // this is equivalent to the following\r\n * events.register(\"loadstart\", object, loadStartListener);\r\n * events.register(\"loadend\", object, loadEndListener);\r\n * (end)\r\n *\r\n * Parameters:\r\n * object - {Object} \r\n */\r\n on: function(object) {\r\n for(var type in object) {\r\n if(type != \"scope\" && object.hasOwnProperty(type)) {\r\n this.register(type, object.scope, object[type]);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: register\r\n * Register an event on the events object.\r\n *\r\n * When the event is triggered, the 'func' function will be called, in the\r\n * context of 'obj'. Imagine we were to register an event, specifying an \r\n * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the \r\n * context in the callback function will be our Bounds object. This means\r\n * that within our callback function, we can access the properties and \r\n * methods of the Bounds object through the \"this\" variable. So our \r\n * callback could execute something like: \r\n * : leftStr = \"Left: \" + this.left;\r\n * \r\n * or\r\n * \r\n * : centerStr = \"Center: \" + this.getCenterLonLat();\r\n *\r\n * Parameters:\r\n * type - {String} Name of the event to register\r\n * obj - {Object} The object to bind the context to for the callback#.\r\n * If no object is specified, default is the Events's 'object' property.\r\n * func - {Function} The callback function. If no callback is \r\n * specified, this function does nothing.\r\n * priority - {Boolean|Object} If true, adds the new listener to the\r\n * *front* of the events queue instead of to the end.\r\n *\r\n * Valid options for priority:\r\n * extension - {Boolean} If true, then the event will be registered as\r\n * extension event. Extension events are handled before all other\r\n * events.\r\n */\r\n register: function (type, obj, func, priority) {\r\n if (type in OpenLayers.Events && !this.extensions[type]) {\r\n this.extensions[type] = new OpenLayers.Events[type](this);\r\n }\r\n if (func != null) {\r\n if (obj == null) {\r\n obj = this.object;\r\n }\r\n var listeners = this.listeners[type];\r\n if (!listeners) {\r\n listeners = [];\r\n this.listeners[type] = listeners;\r\n this.extensionCount[type] = 0;\r\n }\r\n var listener = {obj: obj, func: func};\r\n if (priority) {\r\n listeners.splice(this.extensionCount[type], 0, listener);\r\n if (typeof priority === \"object\" && priority.extension) {\r\n this.extensionCount[type]++;\r\n }\r\n } else {\r\n listeners.push(listener);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: registerPriority\r\n * Same as register() but adds the new listener to the *front* of the\r\n * events queue instead of to the end.\r\n * \r\n * TODO: get rid of this in 3.0 - Decide whether listeners should be \r\n * called in the order they were registered or in reverse order.\r\n *\r\n *\r\n * Parameters:\r\n * type - {String} Name of the event to register\r\n * obj - {Object} The object to bind the context to for the callback#.\r\n * If no object is specified, default is the Events's \r\n * 'object' property.\r\n * func - {Function} The callback function. If no callback is \r\n * specified, this function does nothing.\r\n */\r\n registerPriority: function (type, obj, func) {\r\n this.register(type, obj, func, true);\r\n },\r\n \r\n /**\r\n * APIMethod: un\r\n * Convenience method for unregistering listeners with a common scope.\r\n * Internally, this method calls as shown in the examples\r\n * below.\r\n *\r\n * Example use:\r\n * (code)\r\n * // unregister a single listener for the \"loadstart\" event\r\n * events.un({\"loadstart\": loadStartListener});\r\n *\r\n * // this is equivalent to the following\r\n * events.unregister(\"loadstart\", undefined, loadStartListener);\r\n *\r\n * // unregister multiple listeners with the same `this` object\r\n * events.un({\r\n * \"loadstart\": loadStartListener,\r\n * \"loadend\": loadEndListener,\r\n * scope: object\r\n * });\r\n *\r\n * // this is equivalent to the following\r\n * events.unregister(\"loadstart\", object, loadStartListener);\r\n * events.unregister(\"loadend\", object, loadEndListener);\r\n * (end)\r\n */\r\n un: function(object) {\r\n for(var type in object) {\r\n if(type != \"scope\" && object.hasOwnProperty(type)) {\r\n this.unregister(type, object.scope, object[type]);\r\n }\r\n }\r\n },\r\n\r\n /**\r\n * APIMethod: unregister\r\n *\r\n * Parameters:\r\n * type - {String} \r\n * obj - {Object} If none specified, defaults to this.object\r\n * func - {Function} \r\n */\r\n unregister: function (type, obj, func) {\r\n if (obj == null) {\r\n obj = this.object;\r\n }\r\n var listeners = this.listeners[type];\r\n if (listeners != null) {\r\n for (var i=0, len=listeners.length; i Math.floor(evt.pageY) ||\r\n evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) {\r\n // iOS4 include scroll offset in clientX/Y\r\n x = x - winPageX;\r\n y = y - winPageY;\r\n } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX) ) {\r\n // Some Android browsers have totally bogus values for clientX/Y\r\n // when scrolling/zooming a page\r\n x = evt.pageX - winPageX;\r\n y = evt.pageY - winPageY;\r\n }\r\n \r\n evt.olClientX = x;\r\n evt.olClientY = y;\r\n \r\n return {\r\n clientX: x,\r\n clientY: y\r\n };\r\n },\r\n \r\n /**\r\n * APIMethod: clearMouseCache\r\n * Clear cached data about the mouse position. This should be called any \r\n * time the element that events are registered on changes position \r\n * within the page.\r\n */\r\n clearMouseCache: function() { \r\n this.element.scrolls = null;\r\n this.element.lefttop = null;\r\n this.element.offsets = null;\r\n }, \r\n\r\n /**\r\n * Method: getMousePosition\r\n * \r\n * Parameters:\r\n * evt - {Event} \r\n * \r\n * Returns:\r\n * {} The current xy coordinate of the mouse, adjusted\r\n * for offsets\r\n */\r\n getMousePosition: function (evt) {\r\n if (!this.includeXY) {\r\n this.clearMouseCache();\r\n } else if (!this.element.hasScrollEvent) {\r\n OpenLayers.Event.observe(window, \"scroll\", this.clearMouseListener);\r\n this.element.hasScrollEvent = true;\r\n }\r\n \r\n if (!this.element.scrolls) {\r\n var viewportElement = OpenLayers.Util.getViewportElement();\r\n this.element.scrolls = [\r\n window.pageXOffset || viewportElement.scrollLeft,\r\n window.pageYOffset || viewportElement.scrollTop\r\n ];\r\n }\r\n\r\n if (!this.element.lefttop) {\r\n this.element.lefttop = [\r\n (document.documentElement.clientLeft || 0),\r\n (document.documentElement.clientTop || 0)\r\n ];\r\n }\r\n \r\n if (!this.element.offsets) {\r\n this.element.offsets = OpenLayers.Util.pagePosition(this.element);\r\n }\r\n\r\n return new OpenLayers.Pixel(\r\n (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]\r\n - this.element.lefttop[0], \r\n (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]\r\n - this.element.lefttop[1]\r\n ); \r\n },\r\n\r\n /**\r\n * Method: getTouchModel\r\n * Get the touch model currently in use.\r\n * \r\n * This is cached on OpenLayers.Events as _TOUCH_MODEL \r\n * \r\n * Returns:\r\n * {string} The current touch model (TOUCH_MODEL_xxx), null if none\r\n */\r\n getTouchModel: function() {\r\n if (!(\"_TOUCH_MODEL\" in OpenLayers.Events)) {\r\n OpenLayers.Events._TOUCH_MODEL =\r\n (window.PointerEvent && \"pointer\") ||\r\n (window.MSPointerEvent && \"MSPointer\") ||\r\n ((\"ontouchdown\" in document) && \"touch\") ||\r\n null;\r\n }\r\n return OpenLayers.Events._TOUCH_MODEL;\r\n },\r\n\r\n /**\r\n * Method: addPointerTouchListener\r\n *\r\n * Parameters:\r\n * element - {DOMElement} The DOM element to register the listener on\r\n * type - {String} The event type\r\n * handler - {Function} the handler\r\n */\r\n addPointerTouchListener: function (element, type, handler) {\r\n var eventHandler = this.eventHandler;\r\n var touches = this._pointerTouches;\r\n\r\n function pointerHandler(evt) {\r\n handler(OpenLayers.Util.applyDefaults({\r\n stopPropagation: function() {\r\n for (var i=touches.length-1; i>=0; --i) {\r\n touches[i].stopPropagation();\r\n }\r\n },\r\n preventDefault: function() {\r\n for (var i=touches.length-1; i>=0; --i) {\r\n touches[i].preventDefault();\r\n }\r\n },\r\n type: type\r\n }, evt));\r\n }\r\n\r\n switch (type) {\r\n case 'touchstart':\r\n return this.addPointerTouchListenerStart(element, type, pointerHandler);\r\n case 'touchend':\r\n return this.addPointerTouchListenerEnd(element, type, pointerHandler);\r\n case 'touchmove':\r\n return this.addPointerTouchListenerMove(element, type, pointerHandler);\r\n default:\r\n throw 'Unknown touch event type';\r\n }\r\n },\r\n\r\n /**\r\n * Method: addPointerTouchListenerStart\r\n *\r\n * Parameters:\r\n * element - {DOMElement} The DOM element to register the listener on\r\n * type - {String} The event type\r\n * handler - {Function} the handler\r\n */\r\n addPointerTouchListenerStart: function(element, type, handler) {\r\n var touches = this._pointerTouches;\r\n\r\n var cb = function(e) {\r\n\r\n // pointer could be mouse or pen\r\n if (!OpenLayers.Event.isTouchEvent(e)) {\r\n return;\r\n }\r\n\r\n var alreadyInArray = false;\r\n for (var i=0, ii=touches.length; i= this.clientWidth || Math.ceil(e.clientY) >= this.clientHeight)) {\r\n touches.splice(i, 1);\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n };\r\n OpenLayers.Event.observe(element,\r\n this.getTouchModel() === this.TOUCH_MODEL_MSPOINTER ?\r\n 'MSPointerOut' : 'pointerout',\r\n internalCb);\r\n },\r\n\r\n /**\r\n * Method: addPointerTouchListenerMove\r\n *\r\n * Parameters:\r\n * element - {DOMElement} The DOM element to register the listener on\r\n * type - {String} The event type\r\n * handler - {Function} the handler\r\n */\r\n addPointerTouchListenerMove: function (element, type, handler) {\r\n var touches = this._pointerTouches;\r\n var cb = function(e) {\r\n\r\n // pointer could be mouse or pen\r\n if (!OpenLayers.Event.isTouchEvent(e)) {\r\n return;\r\n }\r\n\r\n if (touches.length == 1 && touches[0].pageX == e.pageX &&\r\n touches[0].pageY == e.pageY) {\r\n // don't trigger event when pointer has not moved\r\n return;\r\n }\r\n for (var i=0, ii=touches.length; i class.\r\n */\r\nif (!OpenLayers.Request) {\r\n /**\r\n * This allows for OpenLayers/Request/XMLHttpRequest.js to be included\r\n * before or after this script.\r\n */\r\n OpenLayers.Request = {};\r\n}\r\nOpenLayers.Util.extend(OpenLayers.Request, {\r\n \r\n /**\r\n * Constant: DEFAULT_CONFIG\r\n * {Object} Default configuration for all requests.\r\n */\r\n DEFAULT_CONFIG: {\r\n method: \"GET\",\r\n url: window.location.href,\r\n async: true,\r\n user: undefined,\r\n password: undefined,\r\n params: null,\r\n proxy: OpenLayers.ProxyHost,\r\n headers: {},\r\n data: null,\r\n callback: function() {},\r\n success: null,\r\n failure: null,\r\n scope: null\r\n },\r\n \r\n /**\r\n * Constant: URL_SPLIT_REGEX\r\n */\r\n URL_SPLIT_REGEX: /([^:]*:)\\/\\/([^:]*:?[^@]*@)?([^:\\/\\?]*):?([^\\/\\?]*)/,\r\n \r\n /**\r\n * APIProperty: events\r\n * {} An events object that handles all \r\n * events on the {} object.\r\n *\r\n * All event listeners will receive an event object with three properties:\r\n * request - {} The request object.\r\n * config - {Object} The config object sent to the specific request method.\r\n * requestUrl - {String} The request url.\r\n * \r\n * Supported event types:\r\n * complete - Triggered when we have a response from the request, if a\r\n * listener returns false, no further response processing will take\r\n * place.\r\n * success - Triggered when the HTTP response has a success code (200-299).\r\n * failure - Triggered when the HTTP response does not have a success code.\r\n */\r\n events: new OpenLayers.Events(this),\r\n \r\n /**\r\n * Method: makeSameOrigin\r\n * Using the specified proxy, returns a same origin url of the provided url.\r\n *\r\n * Parameters:\r\n * url - {String} An arbitrary url\r\n * proxy {String|Function} The proxy to use to make the provided url a\r\n * same origin url.\r\n *\r\n * Returns\r\n * {String} the same origin url. If no proxy is provided, the returned url\r\n * will be the same as the provided url.\r\n */\r\n makeSameOrigin: function(url, proxy) {\r\n var sameOrigin = url.indexOf(\"http\") !== 0;\r\n var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX);\r\n if (urlParts) {\r\n var location = window.location;\r\n sameOrigin =\r\n urlParts[1] == location.protocol &&\r\n urlParts[3] == location.hostname;\r\n var uPort = urlParts[4], lPort = location.port;\r\n if (uPort != 80 && uPort != \"\" || lPort != \"80\" && lPort != \"\") {\r\n sameOrigin = sameOrigin && uPort == lPort;\r\n }\r\n }\r\n if (!sameOrigin) {\r\n if (proxy) {\r\n if (typeof proxy == \"function\") {\r\n url = proxy(url);\r\n } else {\r\n url = proxy + encodeURIComponent(url);\r\n }\r\n }\r\n }\r\n return url;\r\n },\r\n\r\n /**\r\n * APIMethod: issue\r\n * Create a new XMLHttpRequest object, open it, set any headers, bind\r\n * a callback to done state, and send any data. It is recommended that\r\n * you use one , , , , , or .\r\n * This method is only documented to provide detail on the configuration\r\n * options available to all request methods.\r\n *\r\n * Parameters:\r\n * config - {Object} Object containing properties for configuring the\r\n * request. Allowed configuration properties are described below.\r\n * This object is modified and should not be reused.\r\n *\r\n * Allowed config properties:\r\n * method - {String} One of GET, POST, PUT, DELETE, HEAD, or\r\n * OPTIONS. Default is GET.\r\n * url - {String} URL for the request.\r\n * async - {Boolean} Open an asynchronous request. Default is true.\r\n * user - {String} User for relevant authentication scheme. Set\r\n * to null to clear current user.\r\n * password - {String} Password for relevant authentication scheme.\r\n * Set to null to clear current password.\r\n * proxy - {String} Optional proxy. Defaults to\r\n * .\r\n * params - {Object} Any key:value pairs to be appended to the\r\n * url as a query string. Assumes url doesn't already include a query\r\n * string or hash. Typically, this is only appropriate for \r\n * requests where the query string will be appended to the url.\r\n * Parameter values that are arrays will be\r\n * concatenated with a comma (note that this goes against form-encoding)\r\n * as is done with .\r\n * headers - {Object} Object with header:value pairs to be set on\r\n * the request.\r\n * data - {String | Document} Optional data to send with the request.\r\n * Typically, this is only used with and requests.\r\n * Make sure to provide the appropriate \"Content-Type\" header for your\r\n * data. For and requests, the content type defaults to\r\n * \"application-xml\". If your data is a different content type, or\r\n * if you are using a different HTTP method, set the \"Content-Type\"\r\n * header to match your data type.\r\n * callback - {Function} Function to call when request is done.\r\n * To determine if the request failed, check request.status (200\r\n * indicates success).\r\n * success - {Function} Optional function to call if request status is in\r\n * the 200s. This will be called in addition to callback above and\r\n * would typically only be used as an alternative.\r\n * failure - {Function} Optional function to call if request status is not\r\n * in the 200s. This will be called in addition to callback above and\r\n * would typically only be used as an alternative.\r\n * scope - {Object} If callback is a public method on some object,\r\n * set the scope to that object.\r\n *\r\n * Returns:\r\n * {XMLHttpRequest} Request object. To abort the request before a response\r\n * is received, call abort() on the request object.\r\n */\r\n issue: function(config) { \r\n // apply default config - proxy host may have changed\r\n var defaultConfig = OpenLayers.Util.extend(\r\n this.DEFAULT_CONFIG,\r\n {proxy: OpenLayers.ProxyHost}\r\n );\r\n config = config || {};\r\n config.headers = config.headers || {};\r\n config = OpenLayers.Util.applyDefaults(config, defaultConfig);\r\n config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers);\r\n // Always set the \"X-Requested-With\" header to signal that this request\r\n // was issued through the XHR-object. Since header keys are case \r\n // insensitive and we want to allow overriding of the \"X-Requested-With\"\r\n // header through the user we cannot use applyDefaults, but have to \r\n // check manually whether we were called with a \"X-Requested-With\"\r\n // header.\r\n var customRequestedWithHeader = false,\r\n headerKey;\r\n for(headerKey in config.headers) {\r\n if (config.headers.hasOwnProperty( headerKey )) {\r\n if (headerKey.toLowerCase() === 'x-requested-with') {\r\n customRequestedWithHeader = true;\r\n }\r\n }\r\n }\r\n if (customRequestedWithHeader === false) {\r\n // we did not have a custom \"X-Requested-With\" header\r\n config.headers['X-Requested-With'] = 'XMLHttpRequest';\r\n }\r\n\r\n // create request, open, and set headers\r\n var request = new OpenLayers.Request.XMLHttpRequest();\r\n var url = OpenLayers.Util.urlAppend(config.url, \r\n OpenLayers.Util.getParameterString(config.params || {}));\r\n url = OpenLayers.Request.makeSameOrigin(url, config.proxy);\r\n request.open(\r\n config.method, url, config.async, config.user, config.password\r\n );\r\n for(var header in config.headers) {\r\n request.setRequestHeader(header, config.headers[header]);\r\n }\r\n\r\n var events = this.events;\r\n\r\n // we want to execute runCallbacks with \"this\" as the\r\n // execution scope\r\n var self = this;\r\n \r\n request.onreadystatechange = function() {\r\n if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {\r\n var proceed = events.triggerEvent(\r\n \"complete\",\r\n {request: request, config: config, requestUrl: url}\r\n );\r\n if(proceed !== false) {\r\n self.runCallbacks(\r\n {request: request, config: config, requestUrl: url}\r\n );\r\n }\r\n }\r\n };\r\n \r\n // send request (optionally with data) and return\r\n // call in a timeout for asynchronous requests so the return is\r\n // available before readyState == 4 for cached docs\r\n if(config.async === false) {\r\n request.send(config.data);\r\n } else {\r\n window.setTimeout(function(){\r\n if (request.readyState !== 0) { // W3C: 0-UNSENT\r\n request.send(config.data);\r\n }\r\n }, 0);\r\n }\r\n return request;\r\n },\r\n \r\n /**\r\n * Method: runCallbacks\r\n * Calls the complete, success and failure callbacks. Application\r\n * can listen to the \"complete\" event, have the listener \r\n * display a confirm window and always return false, and\r\n * execute OpenLayers.Request.runCallbacks if the user\r\n * hits \"yes\" in the confirm window.\r\n *\r\n * Parameters:\r\n * options - {Object} Hash containing request, config and requestUrl keys\r\n */\r\n runCallbacks: function(options) {\r\n var request = options.request;\r\n var config = options.config;\r\n \r\n // bind callbacks to readyState 4 (done)\r\n var complete = (config.scope) ?\r\n OpenLayers.Function.bind(config.callback, config.scope) :\r\n config.callback;\r\n \r\n // optional success callback\r\n var success;\r\n if(config.success) {\r\n success = (config.scope) ?\r\n OpenLayers.Function.bind(config.success, config.scope) :\r\n config.success;\r\n }\r\n\r\n // optional failure callback\r\n var failure;\r\n if(config.failure) {\r\n failure = (config.scope) ?\r\n OpenLayers.Function.bind(config.failure, config.scope) :\r\n config.failure;\r\n }\r\n\r\n if (OpenLayers.Util.createUrlObject(config.url).protocol == \"file:\" &&\r\n request.responseText) {\r\n request.status = 200;\r\n }\r\n complete(request);\r\n\r\n if (!request.status || (request.status >= 200 && request.status < 300)) {\r\n this.events.triggerEvent(\"success\", options);\r\n if(success) {\r\n success(request);\r\n }\r\n }\r\n if(request.status && (request.status < 200 || request.status >= 300)) { \r\n this.events.triggerEvent(\"failure\", options);\r\n if(failure) {\r\n failure(request);\r\n }\r\n }\r\n },\r\n \r\n /**\r\n * APIMethod: GET\r\n * Send an HTTP GET request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to GET.\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties.\r\n * This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n GET: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"GET\"});\r\n return OpenLayers.Request.issue(config);\r\n },\r\n \r\n /**\r\n * APIMethod: POST\r\n * Send a POST request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to POST and \"Content-Type\" header set to \"application/xml\".\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties. The\r\n * default \"Content-Type\" header will be set to \"application-xml\" if\r\n * none is provided. This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n POST: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"POST\"});\r\n // set content type to application/xml if it isn't already set\r\n config.headers = config.headers ? config.headers : {};\r\n if(!(\"CONTENT-TYPE\" in OpenLayers.Util.upperCaseObject(config.headers))) {\r\n config.headers[\"Content-Type\"] = \"application/xml\";\r\n }\r\n return OpenLayers.Request.issue(config);\r\n },\r\n \r\n /**\r\n * APIMethod: PUT\r\n * Send an HTTP PUT request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to PUT and \"Content-Type\" header set to \"application/xml\".\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties. The\r\n * default \"Content-Type\" header will be set to \"application-xml\" if\r\n * none is provided. This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n PUT: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"PUT\"});\r\n // set content type to application/xml if it isn't already set\r\n config.headers = config.headers ? config.headers : {};\r\n if(!(\"CONTENT-TYPE\" in OpenLayers.Util.upperCaseObject(config.headers))) {\r\n config.headers[\"Content-Type\"] = \"application/xml\";\r\n }\r\n return OpenLayers.Request.issue(config);\r\n },\r\n \r\n /**\r\n * APIMethod: DELETE\r\n * Send an HTTP DELETE request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to DELETE.\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties.\r\n * This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n DELETE: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"DELETE\"});\r\n return OpenLayers.Request.issue(config);\r\n },\r\n \r\n /**\r\n * APIMethod: HEAD\r\n * Send an HTTP HEAD request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to HEAD.\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties.\r\n * This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n HEAD: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"HEAD\"});\r\n return OpenLayers.Request.issue(config);\r\n },\r\n \r\n /**\r\n * APIMethod: OPTIONS\r\n * Send an HTTP OPTIONS request. Additional configuration properties are\r\n * documented in the method, with the method property set\r\n * to OPTIONS.\r\n *\r\n * Parameters:\r\n * config - {Object} Object with properties for configuring the request.\r\n * See the method for documentation of allowed properties.\r\n * This object is modified and should not be reused.\r\n * \r\n * Returns:\r\n * {XMLHttpRequest} Request object.\r\n */\r\n OPTIONS: function(config) {\r\n config = OpenLayers.Util.extend(config, {method: \"OPTIONS\"});\r\n return OpenLayers.Request.issue(config);\r\n }\r\n\r\n});\r\n/* ======================================================================\r\n OpenLayers/Request/XMLHttpRequest.js\r\n ====================================================================== */\r\n\r\n// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)\r\n//\r\n// Licensed under the Apache License, Version 2.0 (the \"License\");\r\n// you may not use this file except in compliance with the License.\r\n// You may obtain a copy of the License at\r\n//\r\n// http://www.apache.org/licenses/LICENSE-2.0\r\n//\r\n// Unless required by applicable law or agreed to in writing, software\r\n// distributed under the License is distributed on an \"AS IS\" BASIS,\r\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n// See the License for the specific language governing permissions and\r\n// limitations under the License.\r\n\r\n/**\r\n * @requires OpenLayers/Request.js\r\n */\r\n\r\n(function () {\r\n\r\n // Save reference to earlier defined object implementation (if any)\r\n var oXMLHttpRequest = window.XMLHttpRequest;\r\n\r\n // Define on browser type\r\n var bGecko = !!window.controllers,\r\n bIE = window.document.all && !window.opera,\r\n bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);\r\n\r\n // Enables \"XMLHttpRequest()\" call next to \"new XMLHttpReques()\"\r\n function fXMLHttpRequest() {\r\n this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject(\"Microsoft.XMLHTTP\");\r\n this._listeners = [];\r\n };\r\n\r\n // Constructor\r\n function cXMLHttpRequest() {\r\n return new fXMLHttpRequest;\r\n };\r\n cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;\r\n\r\n // BUGFIX: Firefox with Firebug installed would break pages if not executed\r\n if (bGecko && oXMLHttpRequest.wrapped)\r\n cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;\r\n\r\n // Constants\r\n cXMLHttpRequest.UNSENT = 0;\r\n cXMLHttpRequest.OPENED = 1;\r\n cXMLHttpRequest.HEADERS_RECEIVED = 2;\r\n cXMLHttpRequest.LOADING = 3;\r\n cXMLHttpRequest.DONE = 4;\r\n\r\n // Public Properties\r\n cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;\r\n cXMLHttpRequest.prototype.responseText = '';\r\n cXMLHttpRequest.prototype.responseXML = null;\r\n cXMLHttpRequest.prototype.status = 0;\r\n cXMLHttpRequest.prototype.statusText = '';\r\n\r\n // Priority proposal\r\n cXMLHttpRequest.prototype.priority = \"NORMAL\";\r\n\r\n // Instance-level Events Handlers\r\n cXMLHttpRequest.prototype.onreadystatechange = null;\r\n\r\n // Class-level Events Handlers\r\n cXMLHttpRequest.onreadystatechange = null;\r\n cXMLHttpRequest.onopen = null;\r\n cXMLHttpRequest.onsend = null;\r\n cXMLHttpRequest.onabort = null;\r\n\r\n // Public Methods\r\n cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {\r\n // Delete headers, required when object is reused\r\n delete this._headers;\r\n\r\n // When bAsync parameter value is omitted, use true as default\r\n if (arguments.length < 3)\r\n bAsync = true;\r\n\r\n // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests\r\n this._async = bAsync;\r\n\r\n // Set the onreadystatechange handler\r\n var oRequest = this,\r\n nState = this.readyState,\r\n fOnUnload;\r\n\r\n // BUGFIX: IE - memory leak on page unload (inter-page leak)\r\n if (bIE && bAsync) {\r\n fOnUnload = function() {\r\n if (nState != cXMLHttpRequest.DONE) {\r\n fCleanTransport(oRequest);\r\n // Safe to abort here since onreadystatechange handler removed\r\n oRequest.abort();\r\n }\r\n };\r\n window.attachEvent(\"onunload\", fOnUnload);\r\n }\r\n\r\n // Add method sniffer\r\n if (cXMLHttpRequest.onopen)\r\n cXMLHttpRequest.onopen.apply(this, arguments);\r\n\r\n if (arguments.length > 4)\r\n this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);\r\n else\r\n if (arguments.length > 3)\r\n this._object.open(sMethod, sUrl, bAsync, sUser);\r\n else\r\n this._object.open(sMethod, sUrl, bAsync);\r\n\r\n this.readyState = cXMLHttpRequest.OPENED;\r\n fReadyStateChange(this);\r\n\r\n this._object.onreadystatechange = function() {\r\n if (bGecko && !bAsync)\r\n return;\r\n\r\n // Synchronize state\r\n oRequest.readyState = oRequest._object.readyState;\r\n\r\n //\r\n fSynchronizeValues(oRequest);\r\n\r\n // BUGFIX: Firefox fires unnecessary DONE when aborting\r\n if (oRequest._aborted) {\r\n // Reset readyState to UNSENT\r\n oRequest.readyState = cXMLHttpRequest.UNSENT;\r\n\r\n // Return now\r\n return;\r\n }\r\n\r\n if (oRequest.readyState == cXMLHttpRequest.DONE) {\r\n // Free up queue\r\n delete oRequest._data;\r\n/* if (bAsync)\r\n fQueue_remove(oRequest);*/\r\n //\r\n fCleanTransport(oRequest);\r\n// Uncomment this block if you need a fix for IE cache\r\n/*\r\n // BUGFIX: IE - cache issue\r\n if (!oRequest._object.getResponseHeader(\"Date\")) {\r\n // Save object to cache\r\n oRequest._cached = oRequest._object;\r\n\r\n // Instantiate a new transport object\r\n cXMLHttpRequest.call(oRequest);\r\n\r\n // Re-send request\r\n if (sUser) {\r\n if (sPassword)\r\n oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);\r\n else\r\n oRequest._object.open(sMethod, sUrl, bAsync, sUser);\r\n }\r\n else\r\n oRequest._object.open(sMethod, sUrl, bAsync);\r\n oRequest._object.setRequestHeader(\"If-Modified-Since\", oRequest._cached.getResponseHeader(\"Last-Modified\") || new window.Date(0));\r\n // Copy headers set\r\n if (oRequest._headers)\r\n for (var sHeader in oRequest._headers)\r\n if (typeof oRequest._headers[sHeader] == \"string\") // Some frameworks prototype objects with functions\r\n oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);\r\n\r\n oRequest._object.onreadystatechange = function() {\r\n // Synchronize state\r\n oRequest.readyState = oRequest._object.readyState;\r\n\r\n if (oRequest._aborted) {\r\n //\r\n oRequest.readyState = cXMLHttpRequest.UNSENT;\r\n\r\n // Return\r\n return;\r\n }\r\n\r\n if (oRequest.readyState == cXMLHttpRequest.DONE) {\r\n // Clean Object\r\n fCleanTransport(oRequest);\r\n\r\n // get cached request\r\n if (oRequest.status == 304)\r\n oRequest._object = oRequest._cached;\r\n\r\n //\r\n delete oRequest._cached;\r\n\r\n //\r\n fSynchronizeValues(oRequest);\r\n\r\n //\r\n fReadyStateChange(oRequest);\r\n\r\n // BUGFIX: IE - memory leak in interrupted\r\n if (bIE && bAsync)\r\n window.detachEvent(\"onunload\", fOnUnload);\r\n }\r\n };\r\n oRequest._object.send(null);\r\n\r\n // Return now - wait until re-sent request is finished\r\n return;\r\n };\r\n*/\r\n // BUGFIX: IE - memory leak in interrupted\r\n if (bIE && bAsync)\r\n window.detachEvent(\"onunload\", fOnUnload);\r\n }\r\n\r\n // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice\r\n if (nState != oRequest.readyState)\r\n fReadyStateChange(oRequest);\r\n\r\n nState = oRequest.readyState;\r\n }\r\n };\r\n function fXMLHttpRequest_send(oRequest) {\r\n oRequest._object.send(oRequest._data);\r\n\r\n // BUGFIX: Gecko - missing readystatechange calls in synchronous requests\r\n if (bGecko && !oRequest._async) {\r\n oRequest.readyState = cXMLHttpRequest.OPENED;\r\n\r\n // Synchronize state\r\n fSynchronizeValues(oRequest);\r\n\r\n // Simulate missing states\r\n while (oRequest.readyState < cXMLHttpRequest.DONE) {\r\n oRequest.readyState++;\r\n fReadyStateChange(oRequest);\r\n // Check if we are aborted\r\n if (oRequest._aborted)\r\n return;\r\n }\r\n }\r\n };\r\n cXMLHttpRequest.prototype.send = function(vData) {\r\n // Add method sniffer\r\n if (cXMLHttpRequest.onsend)\r\n cXMLHttpRequest.onsend.apply(this, arguments);\r\n\r\n if (!arguments.length)\r\n vData = null;\r\n\r\n // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required\r\n // BUGFIX: IE - rewrites any custom mime-type to \"text/xml\" in case an XMLNode is sent\r\n // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)\r\n if (vData && vData.nodeType) {\r\n vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;\r\n if (!this._headers[\"Content-Type\"])\r\n this._object.setRequestHeader(\"Content-Type\", \"application/xml\");\r\n }\r\n\r\n this._data = vData;\r\n/*\r\n // Add to queue\r\n if (this._async)\r\n fQueue_add(this);\r\n else*/\r\n fXMLHttpRequest_send(this);\r\n };\r\n cXMLHttpRequest.prototype.abort = function() {\r\n // Add method sniffer\r\n if (cXMLHttpRequest.onabort)\r\n cXMLHttpRequest.onabort.apply(this, arguments);\r\n\r\n // BUGFIX: Gecko - unnecessary DONE when aborting\r\n if (this.readyState > cXMLHttpRequest.UNSENT)\r\n this._aborted = true;\r\n\r\n this._object.abort();\r\n\r\n // BUGFIX: IE - memory leak\r\n fCleanTransport(this);\r\n\r\n this.readyState = cXMLHttpRequest.UNSENT;\r\n\r\n delete this._data;\r\n/* if (this._async)\r\n fQueue_remove(this);*/\r\n };\r\n cXMLHttpRequest.prototype.getAllResponseHeaders = function() {\r\n return this._object.getAllResponseHeaders();\r\n };\r\n cXMLHttpRequest.prototype.getResponseHeader = function(sName) {\r\n return this._object.getResponseHeader(sName);\r\n };\r\n cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {\r\n // BUGFIX: IE - cache issue\r\n if (!this._headers)\r\n this._headers = {};\r\n this._headers[sName] = sValue;\r\n\r\n return this._object.setRequestHeader(sName, sValue);\r\n };\r\n\r\n // EventTarget interface implementation\r\n cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {\r\n for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\r\n if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)\r\n return;\r\n // Add listener\r\n this._listeners.push([sName, fHandler, bUseCapture]);\r\n };\r\n\r\n cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {\r\n for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\r\n if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)\r\n break;\r\n // Remove listener\r\n if (oListener)\r\n this._listeners.splice(nIndex, 1);\r\n };\r\n\r\n cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {\r\n var oEventPseudo = {\r\n 'type': oEvent.type,\r\n 'target': this,\r\n 'currentTarget':this,\r\n 'eventPhase': 2,\r\n 'bubbles': oEvent.bubbles,\r\n 'cancelable': oEvent.cancelable,\r\n 'timeStamp': oEvent.timeStamp,\r\n 'stopPropagation': function() {}, // There is no flow\r\n 'preventDefault': function() {}, // There is no default action\r\n 'initEvent': function() {} // Original event object should be initialized\r\n };\r\n\r\n // Execute onreadystatechange\r\n if (oEventPseudo.type == \"readystatechange\" && this.onreadystatechange)\r\n (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);\r\n\r\n // Execute listeners\r\n for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\r\n if (oListener[0] == oEventPseudo.type && !oListener[2])\r\n (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);\r\n };\r\n\r\n //\r\n cXMLHttpRequest.prototype.toString = function() {\r\n return '[' + \"object\" + ' ' + \"XMLHttpRequest\" + ']';\r\n };\r\n\r\n cXMLHttpRequest.toString = function() {\r\n return '[' + \"XMLHttpRequest\" + ']';\r\n };\r\n\r\n // Helper function\r\n function fReadyStateChange(oRequest) {\r\n // Sniffing code\r\n if (cXMLHttpRequest.onreadystatechange)\r\n cXMLHttpRequest.onreadystatechange.apply(oRequest);\r\n\r\n // Fake event\r\n oRequest.dispatchEvent({\r\n 'type': \"readystatechange\",\r\n 'bubbles': false,\r\n 'cancelable': false,\r\n 'timeStamp': new Date + 0\r\n });\r\n };\r\n\r\n function fGetDocument(oRequest) {\r\n var oDocument = oRequest.responseXML,\r\n sResponse = oRequest.responseText;\r\n // Try parsing responseText\r\n if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader(\"Content-Type\").match(/[^\\/]+\\/[^\\+]+\\+xml/)) {\r\n oDocument = new window.ActiveXObject(\"Microsoft.XMLDOM\");\r\n oDocument.async = false;\r\n oDocument.validateOnParse = false;\r\n oDocument.loadXML(sResponse);\r\n }\r\n // Check if there is no error in document\r\n if (oDocument)\r\n if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == \"parsererror\"))\r\n return null;\r\n return oDocument;\r\n };\r\n\r\n function fSynchronizeValues(oRequest) {\r\n try { oRequest.responseText = oRequest._object.responseText; } catch (e) {}\r\n try { oRequest.responseXML = fGetDocument(oRequest._object); } catch (e) {}\r\n try { oRequest.status = oRequest._object.status; } catch (e) {}\r\n try { oRequest.statusText = oRequest._object.statusText; } catch (e) {}\r\n };\r\n\r\n function fCleanTransport(oRequest) {\r\n // BUGFIX: IE - memory leak (on-page leak)\r\n oRequest._object.onreadystatechange = new window.Function;\r\n };\r\n/*\r\n // Queue manager\r\n var oQueuePending = {\"CRITICAL\":[],\"HIGH\":[],\"NORMAL\":[],\"LOW\":[],\"LOWEST\":[]},\r\n aQueueRunning = [];\r\n function fQueue_add(oRequest) {\r\n oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : \"NORMAL\"].push(oRequest);\r\n //\r\n setTimeout(fQueue_process);\r\n };\r\n\r\n function fQueue_remove(oRequest) {\r\n for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)\r\n if (bFound)\r\n aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];\r\n else\r\n if (aQueueRunning[nIndex] == oRequest)\r\n bFound = true;\r\n if (bFound)\r\n aQueueRunning.length--;\r\n //\r\n setTimeout(fQueue_process);\r\n };\r\n\r\n function fQueue_process() {\r\n if (aQueueRunning.length < 6) {\r\n for (var sPriority in oQueuePending) {\r\n if (oQueuePending[sPriority].length) {\r\n var oRequest = oQueuePending[sPriority][0];\r\n oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);\r\n //\r\n aQueueRunning.push(oRequest);\r\n // Send request\r\n fXMLHttpRequest_send(oRequest);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n*/\r\n // Internet Explorer 5.0 (missing apply)\r\n if (!window.Function.prototype.apply) {\r\n window.Function.prototype.apply = function(oRequest, oArguments) {\r\n if (!oArguments)\r\n oArguments = [];\r\n oRequest.__func = this;\r\n oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);\r\n delete oRequest.__func;\r\n };\r\n };\r\n\r\n // Register new object with window\r\n /**\r\n * Class: OpenLayers.Request.XMLHttpRequest\r\n * Standard-compliant (W3C) cross-browser implementation of the\r\n * XMLHttpRequest object. From\r\n * http://code.google.com/p/xmlhttprequest/.\r\n */\r\n if (!OpenLayers.Request) {\r\n /**\r\n * This allows for OpenLayers/Request.js to be included\r\n * before or after this script.\r\n */\r\n OpenLayers.Request = {};\r\n }\r\n OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;\r\n})();\r\n/* ======================================================================\r\n OpenLayers/Projection.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Class.js\r\n * @requires OpenLayers/Util.js\r\n */\r\n\r\n/**\r\n * Namespace: OpenLayers.Projection\r\n * Methods for coordinate transforms between coordinate systems. By default,\r\n * OpenLayers ships with the ability to transform coordinates between\r\n * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)\r\n * coordinate reference systems. See the method for details\r\n * on usage.\r\n *\r\n * Additional transforms may be added by using the \r\n * library. If the proj4js library is included, the method \r\n * will work between any two coordinate reference systems with proj4js \r\n * definitions.\r\n *\r\n * If the proj4js library is not included, or if you wish to allow transforms\r\n * between arbitrary coordinate reference systems, use the \r\n * method to register a custom transform method.\r\n */\r\nOpenLayers.Projection = OpenLayers.Class({\r\n\r\n /**\r\n * Property: proj\r\n * {Object} Proj4js.Proj instance.\r\n */\r\n proj: null,\r\n \r\n /**\r\n * Property: projCode\r\n * {String}\r\n */\r\n projCode: null,\r\n \r\n /**\r\n * Property: titleRegEx\r\n * {RegExp} regular expression to strip the title from a proj4js definition\r\n */\r\n titleRegEx: /\\+title=[^\\+]*/,\r\n\r\n /**\r\n * Constructor: OpenLayers.Projection\r\n * This class offers several methods for interacting with a wrapped \r\n * pro4js projection object. \r\n *\r\n * Parameters:\r\n * projCode - {String} A string identifying the Well Known Identifier for\r\n * the projection.\r\n * options - {Object} An optional object to set additional properties\r\n * on the projection.\r\n *\r\n * Returns:\r\n * {} A projection object.\r\n */\r\n initialize: function(projCode, options) {\r\n OpenLayers.Util.extend(this, options);\r\n this.projCode = projCode;\r\n if (typeof Proj4js == \"object\") {\r\n this.proj = new Proj4js.Proj(projCode);\r\n }\r\n },\r\n \r\n /**\r\n * APIMethod: getCode\r\n * Get the string SRS code.\r\n *\r\n * Returns:\r\n * {String} The SRS code.\r\n */\r\n getCode: function() {\r\n return this.proj ? this.proj.srsCode : this.projCode;\r\n },\r\n \r\n /**\r\n * APIMethod: getUnits\r\n * Get the units string for the projection -- returns null if \r\n * proj4js is not available.\r\n *\r\n * Returns:\r\n * {String} The units abbreviation.\r\n */\r\n getUnits: function() {\r\n return this.proj ? this.proj.units : null;\r\n },\r\n\r\n /**\r\n * Method: toString\r\n * Convert projection to string (getCode wrapper).\r\n *\r\n * Returns:\r\n * {String} The projection code.\r\n */\r\n toString: function() {\r\n return this.getCode();\r\n },\r\n\r\n /**\r\n * Method: equals\r\n * Test equality of two projection instances. Determines equality based\r\n * solely on the projection code.\r\n *\r\n * Returns:\r\n * {Boolean} The two projections are equivalent.\r\n */\r\n equals: function(projection) {\r\n var p = projection, equals = false;\r\n if (p) {\r\n if (!(p instanceof OpenLayers.Projection)) {\r\n p = new OpenLayers.Projection(p);\r\n }\r\n if ((typeof Proj4js == \"object\") && this.proj.defData && p.proj.defData) {\r\n equals = this.proj.defData.replace(this.titleRegEx, \"\") ==\r\n p.proj.defData.replace(this.titleRegEx, \"\");\r\n } else if (p.getCode) {\r\n var source = this.getCode(), target = p.getCode();\r\n equals = source == target ||\r\n !!OpenLayers.Projection.transforms[source] &&\r\n OpenLayers.Projection.transforms[source][target] ===\r\n OpenLayers.Projection.nullTransform;\r\n }\r\n }\r\n return equals; \r\n },\r\n\r\n /* Method: destroy\r\n * Destroy projection object.\r\n */\r\n destroy: function() {\r\n delete this.proj;\r\n delete this.projCode;\r\n },\r\n \r\n CLASS_NAME: \"OpenLayers.Projection\" \r\n}); \r\n\r\n/**\r\n * Property: transforms\r\n * {Object} Transforms is an object, with from properties, each of which may\r\n * have a to property. This allows you to define projections without \r\n * requiring support for proj4js to be included.\r\n *\r\n * This object has keys which correspond to a 'source' projection object. The\r\n * keys should be strings, corresponding to the projection.getCode() value.\r\n * Each source projection object should have a set of destination projection\r\n * keys included in the object. \r\n * \r\n * Each value in the destination object should be a transformation function,\r\n * where the function is expected to be passed an object with a .x and a .y\r\n * property. The function should return the object, with the .x and .y\r\n * transformed according to the transformation function.\r\n *\r\n * Note - Properties on this object should not be set directly. To add a\r\n * transform method to this object, use the method. For an\r\n * example of usage, see the OpenLayers.Layer.SphericalMercator file.\r\n */\r\nOpenLayers.Projection.transforms = {};\r\n\r\n/**\r\n * APIProperty: defaults\r\n * {Object} Defaults for the SRS codes known to OpenLayers (currently\r\n * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857,\r\n * EPSG:102113, EPSG:102100 and OSGEO:41001). Keys are the SRS code, values are\r\n * units, maxExtent (the validity extent for the SRS in projected coordinates),\r\n * worldExtent (the world's extent in EPSG:4326) and yx (true if this SRS\r\n * is known to have a reverse axis order).\r\n */\r\nOpenLayers.Projection.defaults = {\r\n \"EPSG:4326\": {\r\n units: \"degrees\",\r\n maxExtent: [-180, -90, 180, 90],\r\n worldExtent: [-180, -90, 180, 90],\r\n yx: true\r\n },\r\n \"CRS:84\": {\r\n units: \"degrees\",\r\n maxExtent: [-180, -90, 180, 90],\r\n worldExtent: [-180, -90, 180, 90]\r\n },\r\n \"EPSG:900913\": {\r\n units: \"m\",\r\n maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34],\r\n worldExtent: [-180, -89, 180, 89]\r\n }\r\n};\r\n\r\n/**\r\n * APIMethod: addTransform\r\n * Set a custom transform method between two projections. Use this method in\r\n * cases where the proj4js lib is not available or where custom projections\r\n * need to be handled.\r\n *\r\n * Parameters:\r\n * from - {String} The code for the source projection\r\n * to - {String} the code for the destination projection\r\n * method - {Function} A function that takes a point as an argument and\r\n * transforms that point from the source to the destination projection\r\n * in place. The original point should be modified.\r\n */\r\nOpenLayers.Projection.addTransform = function(from, to, method) {\r\n if (method === OpenLayers.Projection.nullTransform) {\r\n var defaults = OpenLayers.Projection.defaults[from];\r\n if (defaults && !OpenLayers.Projection.defaults[to]) {\r\n OpenLayers.Projection.defaults[to] = defaults;\r\n }\r\n }\r\n if(!OpenLayers.Projection.transforms[from]) {\r\n OpenLayers.Projection.transforms[from] = {};\r\n }\r\n OpenLayers.Projection.transforms[from][to] = method;\r\n};\r\n\r\n/**\r\n * APIMethod: transform\r\n * Transform a point coordinate from one projection to another. Note that\r\n * the input point is transformed in place.\r\n * \r\n * Parameters:\r\n * point - { | Object} An object with x and y\r\n * properties representing coordinates in those dimensions.\r\n * source - {OpenLayers.Projection} Source map coordinate system\r\n * dest - {OpenLayers.Projection} Destination map coordinate system\r\n *\r\n * Returns:\r\n * point - {object} A transformed coordinate. The original point is modified.\r\n */\r\nOpenLayers.Projection.transform = function(point, source, dest) {\r\n if (source && dest) {\r\n if (!(source instanceof OpenLayers.Projection)) {\r\n source = new OpenLayers.Projection(source);\r\n }\r\n if (!(dest instanceof OpenLayers.Projection)) {\r\n dest = new OpenLayers.Projection(dest);\r\n }\r\n if (source.proj && dest.proj) {\r\n point = Proj4js.transform(source.proj, dest.proj, point);\r\n } else {\r\n var sourceCode = source.getCode();\r\n var destCode = dest.getCode();\r\n var transforms = OpenLayers.Projection.transforms;\r\n if (transforms[sourceCode] && transforms[sourceCode][destCode]) {\r\n transforms[sourceCode][destCode](point);\r\n }\r\n }\r\n }\r\n return point;\r\n};\r\n\r\n/**\r\n * APIFunction: nullTransform\r\n * A null transformation - useful for defining projection aliases when\r\n * proj4js is not available:\r\n *\r\n * (code)\r\n * OpenLayers.Projection.addTransform(\"EPSG:3857\", \"EPSG:900913\",\r\n * OpenLayers.Projection.nullTransform);\r\n * OpenLayers.Projection.addTransform(\"EPSG:900913\", \"EPSG:3857\",\r\n * OpenLayers.Projection.nullTransform);\r\n * (end)\r\n */\r\nOpenLayers.Projection.nullTransform = function(point) {\r\n return point;\r\n};\r\n\r\n/**\r\n * Note: Transforms for web mercator <-> geographic\r\n * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113, EPSG:102100 and \r\n * OSGEO:41001. OpenLayers originally started referring to EPSG:900913 as web\r\n * mercator. The EPSG has declared EPSG:3857 to be web mercator.\r\n * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as\r\n * equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.\r\n * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and\r\n * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis\r\n * order for EPSG:4326. \r\n */\r\n(function() {\r\n\r\n var pole = 20037508.34;\r\n\r\n function inverseMercator(xy) {\r\n xy.x = 180 * xy.x / pole;\r\n xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);\r\n return xy;\r\n }\r\n\r\n function forwardMercator(xy) {\r\n xy.x = xy.x * pole / 180;\r\n var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;\r\n xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34));\r\n return xy;\r\n }\r\n\r\n function map(base, codes) {\r\n var add = OpenLayers.Projection.addTransform;\r\n var same = OpenLayers.Projection.nullTransform;\r\n var i, len, code, other, j;\r\n for (i=0, len=codes.length; i=0; --i) {\r\n map(mercator[i], geographic);\r\n }\r\n for (i=geographic.length-1; i>=0; --i) {\r\n map(geographic[i], mercator);\r\n }\r\n\r\n})();\r\n/* ======================================================================\r\n OpenLayers/Format/KML.js\r\n ====================================================================== */\r\n\r\n/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for\r\n * full list of contributors). Published under the 2-clause BSD license.\r\n * See license.txt in the OpenLayers distribution or repository for the\r\n * full text of the license. */\r\n\r\n/**\r\n * @requires OpenLayers/BaseTypes/Date.js\r\n * @requires OpenLayers/Format/XML.js\r\n * @requires OpenLayers/Feature/Vector.js\r\n * @requires OpenLayers/Geometry/Point.js\r\n * @requires OpenLayers/Geometry/LineString.js\r\n * @requires OpenLayers/Geometry/Polygon.js\r\n * @requires OpenLayers/Geometry/Collection.js\r\n * @requires OpenLayers/Request/XMLHttpRequest.js\r\n * @requires OpenLayers/Projection.js\r\n */\r\n\r\n/**\r\n * Class: OpenLayers.Format.KML\r\n * Read/Write KML. Create a new instance with the \r\n * constructor. \r\n * \r\n * Inherits from:\r\n * - \r\n */\r\nOpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {\r\n \r\n /**\r\n * Property: namespaces\r\n * {Object} Mapping of namespace aliases to namespace URIs.\r\n */\r\n namespaces: {\r\n kml: \"http://www.opengis.net/kml/2.2\",\r\n gx: \"http://www.google.com/kml/ext/2.2\"\r\n },\r\n\r\n /**\r\n * APIProperty: kmlns\r\n * {String} KML Namespace to use. Defaults to 2.0 namespace.\r\n */\r\n kmlns: \"http://earth.google.com/kml/2.0\",\r\n \r\n /** \r\n * APIProperty: placemarksDesc\r\n * {String} Name of the placemarks. Default is \"No description available\".\r\n */\r\n placemarksDesc: \"No description available\",\r\n \r\n /** \r\n * APIProperty: foldersName\r\n * {String} Name of the folders. Default is \"OpenLayers export\".\r\n * If set to null, no name element will be created.\r\n */\r\n foldersName: \"OpenLayers export\",\r\n \r\n /** \r\n * APIProperty: foldersDesc\r\n * {String} Description of the folders. Default is \"Exported on [date].\"\r\n * If set to null, no description element will be created.\r\n */\r\n foldersDesc: \"Exported on \" + new Date(),\r\n \r\n /**\r\n * APIProperty: extractAttributes\r\n * {Boolean} Extract attributes from KML. Default is true.\r\n * Extracting styleUrls requires this to be set to true\r\n * Note that currently only Data and SimpleData \r\n * elements are handled.\r\n */\r\n extractAttributes: true,\r\n \r\n /**\r\n * APIProperty: kvpAttributes\r\n * {Boolean} Only used if extractAttributes is true.\r\n * If set to true, attributes will be simple\r\n * key-value pairs, compatible with other formats,\r\n * Any displayName elements will be ignored.\r\n * If set to false, attributes will be objects,\r\n * retaining any displayName elements, but not\r\n * compatible with other formats. Any CDATA in\r\n * displayName will be read in as a string value.\r\n * Default is false.\r\n */\r\n kvpAttributes: false,\r\n \r\n /**\r\n * Property: extractStyles\r\n * {Boolean} Extract styles from KML. Default is false.\r\n * Extracting styleUrls also requires extractAttributes to be\r\n * set to true\r\n */\r\n extractStyles: false,\r\n \r\n /**\r\n * APIProperty: extractTracks\r\n * {Boolean} Extract gx:Track elements from Placemark elements. Default\r\n * is false. If true, features will be generated for all points in\r\n * all gx:Track elements. Features will have a when (Date) attribute\r\n * based on when elements in the track. If tracks include angle\r\n * elements, features will have heading, tilt, and roll attributes.\r\n * If track point coordinates have three values, features will have\r\n * an altitude attribute with the third coordinate value.\r\n */\r\n extractTracks: false,\r\n \r\n /**\r\n * APIProperty: trackAttributes\r\n * {Array} If is true, points within gx:Track elements will \r\n * be parsed as features with when, heading, tilt, and roll attributes.\r\n * Any additional attribute names can be provided in .\r\n */\r\n trackAttributes: null,\r\n \r\n /**\r\n * Property: internalns\r\n * {String} KML Namespace to use -- defaults to the namespace of the\r\n * Placemark node being parsed, but falls back to kmlns. \r\n */\r\n internalns: null,\r\n\r\n /**\r\n * Property: features\r\n * {Array} Array of features\r\n * \r\n */\r\n features: null,\r\n\r\n /**\r\n * Property: styles\r\n * {Object} Storage of style objects\r\n * \r\n */\r\n styles: null,\r\n \r\n /**\r\n * Property: styleBaseUrl\r\n * {String}\r\n */\r\n styleBaseUrl: \"\",\r\n\r\n /**\r\n * Property: fetched\r\n * {Object} Storage of KML URLs that have been fetched before\r\n * in order to prevent reloading them.\r\n */\r\n fetched: null,\r\n\r\n /**\r\n * APIProperty: maxDepth\r\n * {Integer} Maximum depth for recursive loading external KML URLs \r\n * Defaults to 0: do no external fetching\r\n */\r\n maxDepth: 0,\r\n\r\n /**\r\n * Constructor: OpenLayers.Format.KML\r\n * Create a new parser for KML.\r\n *\r\n * Parameters:\r\n * options - {Object} An optional object whose properties will be set on\r\n * this instance.\r\n */\r\n initialize: function(options) {\r\n // compile regular expressions once instead of every time they are used\r\n this.regExes = {\r\n trimSpace: (/^\\s*|\\s*$/g),\r\n removeSpace: (/\\s*/g),\r\n splitSpace: (/\\s+/),\r\n trimComma: (/\\s*,\\s*/g),\r\n kmlColor: (/(\\w{2})(\\w{2})(\\w{2})(\\w{2})/),\r\n kmlIconPalette: (/root:\\/\\/icons\\/palette-(\\d+)(\\.\\w+)/),\r\n straightBracket: (/\\$\\[(.*?)\\]/g)\r\n };\r\n // KML coordinates are always in longlat WGS84\r\n this.externalProjection = new OpenLayers.Projection(\"EPSG:4326\");\r\n\r\n OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);\r\n },\r\n\r\n /**\r\n * APIMethod: read\r\n * Read data from a string, and return a list of features. \r\n * \r\n * Parameters: \r\n * data - {String} or {DOMElement} data to read/parse.\r\n *\r\n * Returns:\r\n * {Array()} List of features.\r\n */\r\n read: function(data) {\r\n this.features = [];\r\n this.styles = {};\r\n this.fetched = {};\r\n\r\n // Set default options \r\n var options = {\r\n depth: 0,\r\n styleBaseUrl: this.styleBaseUrl\r\n };\r\n\r\n return this.parseData(data, options);\r\n },\r\n\r\n /**\r\n * Method: parseData\r\n * Read data from a string, and return a list of features. \r\n * \r\n * Parameters: \r\n * data - {String} or {DOMElement} data to read/parse.\r\n * options - {Object} Hash of options\r\n *\r\n * Returns:\r\n * {Array()} List of features.\r\n */\r\n parseData: function(data, options) {\r\n if(typeof data == \"string\") {\r\n data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);\r\n }\r\n\r\n // Loop through the following node types in this order and\r\n // process the nodes found \r\n var types = [\"Link\", \"NetworkLink\", \"Style\", \"StyleMap\", \"Placemark\"];\r\n for(var i=0, len=types.length; i and \r\n // Don't do anything if we have reached our maximum depth for recursion\r\n if (options.depth >= this.maxDepth) {\r\n return false;\r\n }\r\n\r\n // increase depth\r\n var newOptions = OpenLayers.Util.extend({}, options);\r\n newOptions.depth++;\r\n\r\n for(var i=0, len=nodes.length; i nodes\r\n * \r\n * Parameters: \r\n * nodes - {Array} of {DOMElement} data to read/parse.\r\n * options - {Object} Hash of options\r\n * \r\n */\r\n parseStyles: function(nodes, options) {\r\n for(var i=0, len=nodes.length; i node and builds the style hash\r\n * accordingly\r\n * \r\n * Parameters: \r\n * node - {DOMElement}