comparison geotemco/platin_original.js @ 0:57bde4830927

first commit
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 24 Mar 2015 11:37:17 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:57bde4830927
1 (function($){
2
3 var jQuery = $;
4 /*
5 * basic.js
6 *
7 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02110-1301 USA
23 */
24
25 /**
26 * basic code which is included first for the minified version
27 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
28 * @release 1.0
29 * @release date: 2012-07-27
30 * @version date: 2012-07-27
31 */
32
33 var arrayIndex = function(array, obj) {
34 if (Array.indexOf) {
35 return array.indexOf(obj);
36 }
37 for (var i = 0; i < array.length; i++) {
38 if (array[i] == obj) {
39 return i;
40 }
41 }
42 return -1;
43 }
44 var GeoTemCoMinifier_urlPrefix;
45 for (var i = 0; i < document.getElementsByTagName("script").length; i++) {
46 var script = document.getElementsByTagName("script")[i];
47 var index = script.src.indexOf("platin.js");
48 if (index == -1) {
49 index = script.src.indexOf("platin-min.js");
50 }
51 if (index != -1) {
52 GeoTemCoMinifier_urlPrefix = script.src.substring(0, index);
53 break;
54 }
55 }
56 // Copyright 2006 Google Inc.
57 //
58 // Licensed under the Apache License, Version 2.0 (the "License");
59 // you may not use this file except in compliance with the License.
60 // You may obtain a copy of the License at
61 //
62 // http://www.apache.org/licenses/LICENSE-2.0
63 //
64 // Unless required by applicable law or agreed to in writing, software
65 // distributed under the License is distributed on an "AS IS" BASIS,
66 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67 // See the License for the specific language governing permissions and
68 // limitations under the License.
69
70
71 // Known Issues:
72 //
73 // * Patterns are not implemented.
74 // * Radial gradient are not implemented. The VML version of these look very
75 // different from the canvas one.
76 // * Clipping paths are not implemented.
77 // * Coordsize. The width and height attribute have higher priority than the
78 // width and height style values which isn't correct.
79 // * Painting mode isn't implemented.
80 // * Canvas width/height should is using content-box by default. IE in
81 // Quirks mode will draw the canvas using border-box. Either change your
82 // doctype to HTML5
83 // (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
84 // or use Box Sizing Behavior from WebFX
85 // (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
86 // * Non uniform scaling does not correctly scale strokes.
87 // * Optimize. There is always room for speed improvements.
88
89 // Only add this code if we do not already have a canvas implementation
90 if (!document.createElement('canvas').getContext) {
91
92 (function() {
93
94 // alias some functions to make (compiled) code shorter
95 var m = Math;
96 var mr = m.round;
97 var ms = m.sin;
98 var mc = m.cos;
99 var abs = m.abs;
100 var sqrt = m.sqrt;
101
102 // this is used for sub pixel precision
103 var Z = 10;
104 var Z2 = Z / 2;
105
106 /**
107 * This funtion is assigned to the <canvas> elements as element.getContext().
108 * @this {HTMLElement}
109 * @return {CanvasRenderingContext2D_}
110 */
111 function getContext() {
112 return this.context_ ||
113 (this.context_ = new CanvasRenderingContext2D_(this));
114 }
115
116 var slice = Array.prototype.slice;
117
118 /**
119 * Binds a function to an object. The returned function will always use the
120 * passed in {@code obj} as {@code this}.
121 *
122 * Example:
123 *
124 * g = bind(f, obj, a, b)
125 * g(c, d) // will do f.call(obj, a, b, c, d)
126 *
127 * @param {Function} f The function to bind the object to
128 * @param {Object} obj The object that should act as this when the function
129 * is called
130 * @param {*} var_args Rest arguments that will be used as the initial
131 * arguments when the function is called
132 * @return {Function} A new function that has bound this
133 */
134 function bind(f, obj, var_args) {
135 var a = slice.call(arguments, 2);
136 return function() {
137 return f.apply(obj, a.concat(slice.call(arguments)));
138 };
139 }
140
141 var G_vmlCanvasManager_ = {
142 init: function(opt_doc) {
143 if (/MSIE/.test(navigator.userAgent) && !window.opera) {
144 var doc = opt_doc || document;
145 // Create a dummy element so that IE will allow canvas elements to be
146 // recognized.
147 doc.createElement('canvas');
148 doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
149 }
150 },
151
152 init_: function(doc) {
153 // create xmlns
154 if (!doc.namespaces['g_vml_']) {
155 doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
156 '#default#VML');
157
158 }
159 if (!doc.namespaces['g_o_']) {
160 doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
161 '#default#VML');
162 }
163
164 // Setup default CSS. Only add one style sheet per document
165 if (!doc.styleSheets['ex_canvas_']) {
166 var ss = doc.createStyleSheet();
167 ss.owningElement.id = 'ex_canvas_';
168 ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
169 // default size is 300x150 in Gecko and Opera
170 'text-align:left;width:300px;height:150px}' +
171 'g_vml_\\:*{behavior:url(#default#VML)}' +
172 'g_o_\\:*{behavior:url(#default#VML)}';
173
174 }
175
176 // find all canvas elements
177 var els = doc.getElementsByTagName('canvas');
178 for (var i = 0; i < els.length; i++) {
179 this.initElement(els[i]);
180 }
181 },
182
183 /**
184 * Public initializes a canvas element so that it can be used as canvas
185 * element from now on. This is called automatically before the page is
186 * loaded but if you are creating elements using createElement you need to
187 * make sure this is called on the element.
188 * @param {HTMLElement} el The canvas element to initialize.
189 * @return {HTMLElement} the element that was created.
190 */
191 initElement: function(el) {
192 if (!el.getContext) {
193
194 el.getContext = getContext;
195
196 // Remove fallback content. There is no way to hide text nodes so we
197 // just remove all childNodes. We could hide all elements and remove
198 // text nodes but who really cares about the fallback content.
199 el.innerHTML = '';
200
201 // do not use inline function because that will leak memory
202 el.attachEvent('onpropertychange', onPropertyChange);
203 el.attachEvent('onresize', onResize);
204
205 var attrs = el.attributes;
206 if (attrs.width && attrs.width.specified) {
207 // TODO: use runtimeStyle and coordsize
208 // el.getContext().setWidth_(attrs.width.nodeValue);
209 el.style.width = attrs.width.nodeValue + 'px';
210 } else {
211 el.width = el.clientWidth;
212 }
213 if (attrs.height && attrs.height.specified) {
214 // TODO: use runtimeStyle and coordsize
215 // el.getContext().setHeight_(attrs.height.nodeValue);
216 el.style.height = attrs.height.nodeValue + 'px';
217 } else {
218 el.height = el.clientHeight;
219 }
220 //el.getContext().setCoordsize_()
221 }
222 return el;
223 }
224 };
225
226 function onPropertyChange(e) {
227 var el = e.srcElement;
228
229 switch (e.propertyName) {
230 case 'width':
231 el.style.width = el.attributes.width.nodeValue + 'px';
232 el.getContext().clearRect();
233 break;
234 case 'height':
235 el.style.height = el.attributes.height.nodeValue + 'px';
236 el.getContext().clearRect();
237 break;
238 }
239 }
240
241 function onResize(e) {
242 var el = e.srcElement;
243 if (el.firstChild) {
244 el.firstChild.style.width = el.clientWidth + 'px';
245 el.firstChild.style.height = el.clientHeight + 'px';
246 }
247 }
248
249 G_vmlCanvasManager_.init();
250
251 // precompute "00" to "FF"
252 var dec2hex = [];
253 for (var i = 0; i < 16; i++) {
254 for (var j = 0; j < 16; j++) {
255 dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
256 }
257 }
258
259 function createMatrixIdentity() {
260 return [
261 [1, 0, 0],
262 [0, 1, 0],
263 [0, 0, 1]
264 ];
265 }
266
267 function matrixMultiply(m1, m2) {
268 var result = createMatrixIdentity();
269
270 for (var x = 0; x < 3; x++) {
271 for (var y = 0; y < 3; y++) {
272 var sum = 0;
273
274 for (var z = 0; z < 3; z++) {
275 sum += m1[x][z] * m2[z][y];
276 }
277
278 result[x][y] = sum;
279 }
280 }
281 return result;
282 }
283
284 function copyState(o1, o2) {
285 o2.fillStyle = o1.fillStyle;
286 o2.lineCap = o1.lineCap;
287 o2.lineJoin = o1.lineJoin;
288 o2.lineWidth = o1.lineWidth;
289 o2.miterLimit = o1.miterLimit;
290 o2.shadowBlur = o1.shadowBlur;
291 o2.shadowColor = o1.shadowColor;
292 o2.shadowOffsetX = o1.shadowOffsetX;
293 o2.shadowOffsetY = o1.shadowOffsetY;
294 o2.strokeStyle = o1.strokeStyle;
295 o2.globalAlpha = o1.globalAlpha;
296 o2.arcScaleX_ = o1.arcScaleX_;
297 o2.arcScaleY_ = o1.arcScaleY_;
298 o2.lineScale_ = o1.lineScale_;
299 }
300
301 function processStyle(styleString) {
302 var str, alpha = 1;
303
304 styleString = String(styleString);
305 if (styleString.substring(0, 3) == 'rgb') {
306 var start = styleString.indexOf('(', 3);
307 var end = styleString.indexOf(')', start + 1);
308 var guts = styleString.substring(start + 1, end).split(',');
309
310 str = '#';
311 for (var i = 0; i < 3; i++) {
312 str += dec2hex[Number(guts[i])];
313 }
314
315 if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
316 alpha = guts[3];
317 }
318 } else {
319 str = styleString;
320 }
321
322 return {color: str, alpha: alpha};
323 }
324
325 function processLineCap(lineCap) {
326 switch (lineCap) {
327 case 'butt':
328 return 'flat';
329 case 'round':
330 return 'round';
331 case 'square':
332 default:
333 return 'square';
334 }
335 }
336
337 /**
338 * This class implements CanvasRenderingContext2D interface as described by
339 * the WHATWG.
340 * @param {HTMLElement} surfaceElement The element that the 2D context should
341 * be associated with
342 */
343 function CanvasRenderingContext2D_(surfaceElement) {
344 this.m_ = createMatrixIdentity();
345
346 this.mStack_ = [];
347 this.aStack_ = [];
348 this.currentPath_ = [];
349
350 // Canvas context properties
351 this.strokeStyle = '#000';
352 this.fillStyle = '#000';
353
354 this.lineWidth = 1;
355 this.lineJoin = 'miter';
356 this.lineCap = 'butt';
357 this.miterLimit = Z * 1;
358 this.globalAlpha = 1;
359 this.canvas = surfaceElement;
360
361 var el = surfaceElement.ownerDocument.createElement('div');
362 el.style.width = surfaceElement.clientWidth + 'px';
363 el.style.height = surfaceElement.clientHeight + 'px';
364 el.style.overflow = 'hidden';
365 el.style.position = 'absolute';
366 surfaceElement.appendChild(el);
367
368 this.element_ = el;
369 this.arcScaleX_ = 1;
370 this.arcScaleY_ = 1;
371 this.lineScale_ = 1;
372 }
373
374 var contextPrototype = CanvasRenderingContext2D_.prototype;
375 contextPrototype.clearRect = function() {
376 this.element_.innerHTML = '';
377 };
378
379 contextPrototype.beginPath = function() {
380 // TODO: Branch current matrix so that save/restore has no effect
381 // as per safari docs.
382 this.currentPath_ = [];
383 };
384
385 contextPrototype.moveTo = function(aX, aY) {
386 var p = this.getCoords_(aX, aY);
387 this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
388 this.currentX_ = p.x;
389 this.currentY_ = p.y;
390 };
391
392 contextPrototype.lineTo = function(aX, aY) {
393 var p = this.getCoords_(aX, aY);
394 this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});
395
396 this.currentX_ = p.x;
397 this.currentY_ = p.y;
398 };
399
400 contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
401 aCP2x, aCP2y,
402 aX, aY) {
403 var p = this.getCoords_(aX, aY);
404 var cp1 = this.getCoords_(aCP1x, aCP1y);
405 var cp2 = this.getCoords_(aCP2x, aCP2y);
406 bezierCurveTo(this, cp1, cp2, p);
407 };
408
409 // Helper function that takes the already fixed cordinates.
410 function bezierCurveTo(self, cp1, cp2, p) {
411 self.currentPath_.push({
412 type: 'bezierCurveTo',
413 cp1x: cp1.x,
414 cp1y: cp1.y,
415 cp2x: cp2.x,
416 cp2y: cp2.y,
417 x: p.x,
418 y: p.y
419 });
420 self.currentX_ = p.x;
421 self.currentY_ = p.y;
422 }
423
424 contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
425 // the following is lifted almost directly from
426 // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
427
428 var cp = this.getCoords_(aCPx, aCPy);
429 var p = this.getCoords_(aX, aY);
430
431 var cp1 = {
432 x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
433 y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
434 };
435 var cp2 = {
436 x: cp1.x + (p.x - this.currentX_) / 3.0,
437 y: cp1.y + (p.y - this.currentY_) / 3.0
438 };
439
440 bezierCurveTo(this, cp1, cp2, p);
441 };
442
443 contextPrototype.arc = function(aX, aY, aRadius,
444 aStartAngle, aEndAngle, aClockwise) {
445 aRadius *= Z;
446 var arcType = aClockwise ? 'at' : 'wa';
447
448 var xStart = aX + mc(aStartAngle) * aRadius - Z2;
449 var yStart = aY + ms(aStartAngle) * aRadius - Z2;
450
451 var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
452 var yEnd = aY + ms(aEndAngle) * aRadius - Z2;
453
454 // IE won't render arches drawn counter clockwise if xStart == xEnd.
455 if (xStart == xEnd && !aClockwise) {
456 xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
457 // that can be represented in binary
458 }
459
460 var p = this.getCoords_(aX, aY);
461 var pStart = this.getCoords_(xStart, yStart);
462 var pEnd = this.getCoords_(xEnd, yEnd);
463
464 this.currentPath_.push({type: arcType,
465 x: p.x,
466 y: p.y,
467 radius: aRadius,
468 xStart: pStart.x,
469 yStart: pStart.y,
470 xEnd: pEnd.x,
471 yEnd: pEnd.y});
472
473 };
474
475 contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
476 this.moveTo(aX, aY);
477 this.lineTo(aX + aWidth, aY);
478 this.lineTo(aX + aWidth, aY + aHeight);
479 this.lineTo(aX, aY + aHeight);
480 this.closePath();
481 };
482
483 contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
484 var oldPath = this.currentPath_;
485 this.beginPath();
486
487 this.moveTo(aX, aY);
488 this.lineTo(aX + aWidth, aY);
489 this.lineTo(aX + aWidth, aY + aHeight);
490 this.lineTo(aX, aY + aHeight);
491 this.closePath();
492 this.stroke();
493
494 this.currentPath_ = oldPath;
495 };
496
497 contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
498 var oldPath = this.currentPath_;
499 this.beginPath();
500
501 this.moveTo(aX, aY);
502 this.lineTo(aX + aWidth, aY);
503 this.lineTo(aX + aWidth, aY + aHeight);
504 this.lineTo(aX, aY + aHeight);
505 this.closePath();
506 this.fill();
507
508 this.currentPath_ = oldPath;
509 };
510
511 contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
512 var gradient = new CanvasGradient_('gradient');
513 gradient.x0_ = aX0;
514 gradient.y0_ = aY0;
515 gradient.x1_ = aX1;
516 gradient.y1_ = aY1;
517 return gradient;
518 };
519
520 contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
521 aX1, aY1, aR1) {
522 var gradient = new CanvasGradient_('gradientradial');
523 gradient.x0_ = aX0;
524 gradient.y0_ = aY0;
525 gradient.r0_ = aR0;
526 gradient.x1_ = aX1;
527 gradient.y1_ = aY1;
528 gradient.r1_ = aR1;
529 return gradient;
530 };
531
532 contextPrototype.drawImage = function(image, var_args) {
533 var dx, dy, dw, dh, sx, sy, sw, sh;
534
535 // to find the original width we overide the width and height
536 var oldRuntimeWidth = image.runtimeStyle.width;
537 var oldRuntimeHeight = image.runtimeStyle.height;
538 image.runtimeStyle.width = 'auto';
539 image.runtimeStyle.height = 'auto';
540
541 // get the original size
542 var w = image.width;
543 var h = image.height;
544
545 // and remove overides
546 image.runtimeStyle.width = oldRuntimeWidth;
547 image.runtimeStyle.height = oldRuntimeHeight;
548
549 if (arguments.length == 3) {
550 dx = arguments[1];
551 dy = arguments[2];
552 sx = sy = 0;
553 sw = dw = w;
554 sh = dh = h;
555 } else if (arguments.length == 5) {
556 dx = arguments[1];
557 dy = arguments[2];
558 dw = arguments[3];
559 dh = arguments[4];
560 sx = sy = 0;
561 sw = w;
562 sh = h;
563 } else if (arguments.length == 9) {
564 sx = arguments[1];
565 sy = arguments[2];
566 sw = arguments[3];
567 sh = arguments[4];
568 dx = arguments[5];
569 dy = arguments[6];
570 dw = arguments[7];
571 dh = arguments[8];
572 } else {
573 throw Error('Invalid number of arguments');
574 }
575
576 var d = this.getCoords_(dx, dy);
577
578 var w2 = sw / 2;
579 var h2 = sh / 2;
580
581 var vmlStr = [];
582
583 var W = 10;
584 var H = 10;
585
586 // For some reason that I've now forgotten, using divs didn't work
587 vmlStr.push(' <g_vml_:group',
588 ' coordsize="', Z * W, ',', Z * H, '"',
589 ' coordorigin="0,0"' ,
590 ' style="width:', W, 'px;height:', H, 'px;position:absolute;');
591
592 // If filters are necessary (rotation exists), create them
593 // filters are bog-slow, so only create them if abbsolutely necessary
594 // The following check doesn't account for skews (which don't exist
595 // in the canvas spec (yet) anyway.
596
597 if (this.m_[0][0] != 1 || this.m_[0][1]) {
598 var filter = [];
599
600 // Note the 12/21 reversal
601 filter.push('M11=', this.m_[0][0], ',',
602 'M12=', this.m_[1][0], ',',
603 'M21=', this.m_[0][1], ',',
604 'M22=', this.m_[1][1], ',',
605 'Dx=', mr(d.x / Z), ',',
606 'Dy=', mr(d.y / Z), '');
607
608 // Bounding box calculation (need to minimize displayed area so that
609 // filters don't waste time on unused pixels.
610 var max = d;
611 var c2 = this.getCoords_(dx + dw, dy);
612 var c3 = this.getCoords_(dx, dy + dh);
613 var c4 = this.getCoords_(dx + dw, dy + dh);
614
615 max.x = m.max(max.x, c2.x, c3.x, c4.x);
616 max.y = m.max(max.y, c2.y, c3.y, c4.y);
617
618 vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
619 'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
620 filter.join(''), ", sizingmethod='clip');")
621 } else {
622 vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
623 }
624
625 vmlStr.push(' ">' ,
626 '<g_vml_:image src="', image.src, '"',
627 ' style="width:', Z * dw, 'px;',
628 ' height:', Z * dh, 'px;"',
629 ' cropleft="', sx / w, '"',
630 ' croptop="', sy / h, '"',
631 ' cropright="', (w - sx - sw) / w, '"',
632 ' cropbottom="', (h - sy - sh) / h, '"',
633 ' />',
634 '</g_vml_:group>');
635
636 this.element_.insertAdjacentHTML('BeforeEnd',
637 vmlStr.join(''));
638 };
639
640 contextPrototype.stroke = function(aFill) {
641 var lineStr = [];
642 var lineOpen = false;
643 var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
644 var color = a.color;
645 var opacity = a.alpha * this.globalAlpha;
646
647 var W = 10;
648 var H = 10;
649
650 lineStr.push('<g_vml_:shape',
651 ' filled="', !!aFill, '"',
652 ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
653 ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
654 ' stroked="', !aFill, '"',
655 ' path="');
656
657 var newSeq = false;
658 var min = {x: null, y: null};
659 var max = {x: null, y: null};
660
661 for (var i = 0; i < this.currentPath_.length; i++) {
662 var p = this.currentPath_[i];
663 var c;
664
665 switch (p.type) {
666 case 'moveTo':
667 c = p;
668 lineStr.push(' m ', mr(p.x), ',', mr(p.y));
669 break;
670 case 'lineTo':
671 lineStr.push(' l ', mr(p.x), ',', mr(p.y));
672 break;
673 case 'close':
674 lineStr.push(' x ');
675 p = null;
676 break;
677 case 'bezierCurveTo':
678 lineStr.push(' c ',
679 mr(p.cp1x), ',', mr(p.cp1y), ',',
680 mr(p.cp2x), ',', mr(p.cp2y), ',',
681 mr(p.x), ',', mr(p.y));
682 break;
683 case 'at':
684 case 'wa':
685 lineStr.push(' ', p.type, ' ',
686 mr(p.x - this.arcScaleX_ * p.radius), ',',
687 mr(p.y - this.arcScaleY_ * p.radius), ' ',
688 mr(p.x + this.arcScaleX_ * p.radius), ',',
689 mr(p.y + this.arcScaleY_ * p.radius), ' ',
690 mr(p.xStart), ',', mr(p.yStart), ' ',
691 mr(p.xEnd), ',', mr(p.yEnd));
692 break;
693 }
694
695
696 // TODO: Following is broken for curves due to
697 // move to proper paths.
698
699 // Figure out dimensions so we can do gradient fills
700 // properly
701 if (p) {
702 if (min.x == null || p.x < min.x) {
703 min.x = p.x;
704 }
705 if (max.x == null || p.x > max.x) {
706 max.x = p.x;
707 }
708 if (min.y == null || p.y < min.y) {
709 min.y = p.y;
710 }
711 if (max.y == null || p.y > max.y) {
712 max.y = p.y;
713 }
714 }
715 }
716 lineStr.push(' ">');
717
718 if (!aFill) {
719 var lineWidth = this.lineScale_ * this.lineWidth;
720
721 // VML cannot correctly render a line if the width is less than 1px.
722 // In that case, we dilute the color to make the line look thinner.
723 if (lineWidth < 1) {
724 opacity *= lineWidth;
725 }
726
727 lineStr.push(
728 '<g_vml_:stroke',
729 ' opacity="', opacity, '"',
730 ' joinstyle="', this.lineJoin, '"',
731 ' miterlimit="', this.miterLimit, '"',
732 ' endcap="', processLineCap(this.lineCap), '"',
733 ' weight="', lineWidth, 'px"',
734 ' color="', color, '" />'
735 );
736 } else if (typeof this.fillStyle == 'object') {
737 var fillStyle = this.fillStyle;
738 var angle = 0;
739 var focus = {x: 0, y: 0};
740
741 // additional offset
742 var shift = 0;
743 // scale factor for offset
744 var expansion = 1;
745
746 if (fillStyle.type_ == 'gradient') {
747 var x0 = fillStyle.x0_ / this.arcScaleX_;
748 var y0 = fillStyle.y0_ / this.arcScaleY_;
749 var x1 = fillStyle.x1_ / this.arcScaleX_;
750 var y1 = fillStyle.y1_ / this.arcScaleY_;
751 var p0 = this.getCoords_(x0, y0);
752 var p1 = this.getCoords_(x1, y1);
753 var dx = p1.x - p0.x;
754 var dy = p1.y - p0.y;
755 angle = Math.atan2(dx, dy) * 180 / Math.PI;
756
757 // The angle should be a non-negative number.
758 if (angle < 0) {
759 angle += 360;
760 }
761
762 // Very small angles produce an unexpected result because they are
763 // converted to a scientific notation string.
764 if (angle < 1e-6) {
765 angle = 0;
766 }
767 } else {
768 var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
769 var width = max.x - min.x;
770 var height = max.y - min.y;
771 focus = {
772 x: (p0.x - min.x) / width,
773 y: (p0.y - min.y) / height
774 };
775
776 width /= this.arcScaleX_ * Z;
777 height /= this.arcScaleY_ * Z;
778 var dimension = m.max(width, height);
779 shift = 2 * fillStyle.r0_ / dimension;
780 expansion = 2 * fillStyle.r1_ / dimension - shift;
781 }
782
783 // We need to sort the color stops in ascending order by offset,
784 // otherwise IE won't interpret it correctly.
785 var stops = fillStyle.colors_;
786 stops.sort(function(cs1, cs2) {
787 return cs1.offset - cs2.offset;
788 });
789
790 var length = stops.length;
791 var color1 = stops[0].color;
792 var color2 = stops[length - 1].color;
793 var opacity1 = stops[0].alpha * this.globalAlpha;
794 var opacity2 = stops[length - 1].alpha * this.globalAlpha;
795
796 var colors = [];
797 for (var i = 0; i < length; i++) {
798 var stop = stops[i];
799 colors.push(stop.offset * expansion + shift + ' ' + stop.color);
800 }
801
802 // When colors attribute is used, the meanings of opacity and o:opacity2
803 // are reversed.
804 lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
805 ' method="none" focus="100%"',
806 ' color="', color1, '"',
807 ' color2="', color2, '"',
808 ' colors="', colors.join(','), '"',
809 ' opacity="', opacity2, '"',
810 ' g_o_:opacity2="', opacity1, '"',
811 ' angle="', angle, '"',
812 ' focusposition="', focus.x, ',', focus.y, '" />');
813 } else {
814 lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
815 '" />');
816 }
817
818 lineStr.push('</g_vml_:shape>');
819
820 this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
821 };
822
823 contextPrototype.fill = function() {
824 this.stroke(true);
825 }
826
827 contextPrototype.closePath = function() {
828 this.currentPath_.push({type: 'close'});
829 };
830
831 /**
832 * @private
833 */
834 contextPrototype.getCoords_ = function(aX, aY) {
835 var m = this.m_;
836 return {
837 x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
838 y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
839 }
840 };
841
842 contextPrototype.save = function() {
843 var o = {};
844 copyState(this, o);
845 this.aStack_.push(o);
846 this.mStack_.push(this.m_);
847 this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
848 };
849
850 contextPrototype.restore = function() {
851 copyState(this.aStack_.pop(), this);
852 this.m_ = this.mStack_.pop();
853 };
854
855 function matrixIsFinite(m) {
856 for (var j = 0; j < 3; j++) {
857 for (var k = 0; k < 2; k++) {
858 if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
859 return false;
860 }
861 }
862 }
863 return true;
864 }
865
866 function setM(ctx, m, updateLineScale) {
867 if (!matrixIsFinite(m)) {
868 return;
869 }
870 ctx.m_ = m;
871
872 if (updateLineScale) {
873 // Get the line scale.
874 // Determinant of this.m_ means how much the area is enlarged by the
875 // transformation. So its square root can be used as a scale factor
876 // for width.
877 var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
878 ctx.lineScale_ = sqrt(abs(det));
879 }
880 }
881
882 contextPrototype.translate = function(aX, aY) {
883 var m1 = [
884 [1, 0, 0],
885 [0, 1, 0],
886 [aX, aY, 1]
887 ];
888
889 setM(this, matrixMultiply(m1, this.m_), false);
890 };
891
892 contextPrototype.rotate = function(aRot) {
893 var c = mc(aRot);
894 var s = ms(aRot);
895
896 var m1 = [
897 [c, s, 0],
898 [-s, c, 0],
899 [0, 0, 1]
900 ];
901
902 setM(this, matrixMultiply(m1, this.m_), false);
903 };
904
905 contextPrototype.scale = function(aX, aY) {
906 this.arcScaleX_ *= aX;
907 this.arcScaleY_ *= aY;
908 var m1 = [
909 [aX, 0, 0],
910 [0, aY, 0],
911 [0, 0, 1]
912 ];
913
914 setM(this, matrixMultiply(m1, this.m_), true);
915 };
916
917 contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
918 var m1 = [
919 [m11, m12, 0],
920 [m21, m22, 0],
921 [dx, dy, 1]
922 ];
923
924 setM(this, matrixMultiply(m1, this.m_), true);
925 };
926
927 contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
928 var m = [
929 [m11, m12, 0],
930 [m21, m22, 0],
931 [dx, dy, 1]
932 ];
933
934 setM(this, m, true);
935 };
936
937 /******** STUBS ********/
938 contextPrototype.clip = function() {
939 // TODO: Implement
940 };
941
942 contextPrototype.arcTo = function() {
943 // TODO: Implement
944 };
945
946 contextPrototype.createPattern = function() {
947 return new CanvasPattern_;
948 };
949
950 // Gradient / Pattern Stubs
951 function CanvasGradient_(aType) {
952 this.type_ = aType;
953 this.x0_ = 0;
954 this.y0_ = 0;
955 this.r0_ = 0;
956 this.x1_ = 0;
957 this.y1_ = 0;
958 this.r1_ = 0;
959 this.colors_ = [];
960 }
961
962 CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
963 aColor = processStyle(aColor);
964 this.colors_.push({offset: aOffset,
965 color: aColor.color,
966 alpha: aColor.alpha});
967 };
968
969 function CanvasPattern_() {}
970
971 // set up externs
972 G_vmlCanvasManager = G_vmlCanvasManager_;
973 CanvasRenderingContext2D = CanvasRenderingContext2D_;
974 CanvasGradient = CanvasGradient_;
975 CanvasPattern = CanvasPattern_;
976
977 })();
978
979 } // if
980 /*----------------------------------------------------------------------------\
981 | Range Class |
982 |-----------------------------------------------------------------------------|
983 | Created by Erik Arvidsson |
984 | (http://webfx.eae.net/contact.html#erik) |
985 | For WebFX (http://webfx.eae.net/) |
986 |-----------------------------------------------------------------------------|
987 | Used to model the data used when working with sliders, scrollbars and |
988 | progress bars. Based on the ideas of the javax.swing.BoundedRangeModel |
989 | interface defined by Sun for Java; http://java.sun.com/products/jfc/ |
990 | swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html |
991 |-----------------------------------------------------------------------------|
992 | Copyright (c) 2002, 2005, 2006 Erik Arvidsson |
993 |-----------------------------------------------------------------------------|
994 | Licensed under the Apache License, Version 2.0 (the "License"); you may not |
995 | use this file except in compliance with the License. You may obtain a copy |
996 | of the License at http://www.apache.org/licenses/LICENSE-2.0 |
997 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
998 | Unless required by applicable law or agreed to in writing, software |
999 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1000 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1001 | License for the specific language governing permissions and limitations |
1002 | under the License. |
1003 |-----------------------------------------------------------------------------|
1004 | 2002-10-14 | Original version released |
1005 | 2005-10-27 | Use Math.round instead of Math.floor |
1006 | 2006-05-28 | Changed license to Apache Software License 2.0. |
1007 |-----------------------------------------------------------------------------|
1008 | Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
1009 \----------------------------------------------------------------------------*/
1010
1011
1012 function Range() {
1013 this._value = 0;
1014 this._minimum = 0;
1015 this._maximum = 100;
1016 this._extent = 0;
1017
1018 this._isChanging = false;
1019 }
1020
1021 Range.prototype.setValue = function (value) {
1022 value = Math.round(parseFloat(value));
1023 if (isNaN(value)) return;
1024 if (this._value != value) {
1025 if (value + this._extent > this._maximum)
1026 this._value = this._maximum - this._extent;
1027 else if (value < this._minimum)
1028 this._value = this._minimum;
1029 else
1030 this._value = value;
1031 if (!this._isChanging && typeof this.onchange == "function")
1032 this.onchange();
1033 }
1034 };
1035
1036 Range.prototype.getValue = function () {
1037 return this._value;
1038 };
1039
1040 Range.prototype.setExtent = function (extent) {
1041 if (this._extent != extent) {
1042 if (extent < 0)
1043 this._extent = 0;
1044 else if (this._value + extent > this._maximum)
1045 this._extent = this._maximum - this._value;
1046 else
1047 this._extent = extent;
1048 if (!this._isChanging && typeof this.onchange == "function")
1049 this.onchange();
1050 }
1051 };
1052
1053 Range.prototype.getExtent = function () {
1054 return this._extent;
1055 };
1056
1057 Range.prototype.setMinimum = function (minimum) {
1058 if (this._minimum != minimum) {
1059 var oldIsChanging = this._isChanging;
1060 this._isChanging = true;
1061
1062 this._minimum = minimum;
1063
1064 if (minimum > this._value)
1065 this.setValue(minimum);
1066 if (minimum > this._maximum) {
1067 this._extent = 0;
1068 this.setMaximum(minimum);
1069 this.setValue(minimum)
1070 }
1071 if (minimum + this._extent > this._maximum)
1072 this._extent = this._maximum - this._minimum;
1073
1074 this._isChanging = oldIsChanging;
1075 if (!this._isChanging && typeof this.onchange == "function")
1076 this.onchange();
1077 }
1078 };
1079
1080 Range.prototype.getMinimum = function () {
1081 return this._minimum;
1082 };
1083
1084 Range.prototype.setMaximum = function (maximum) {
1085 if (this._maximum != maximum) {
1086 var oldIsChanging = this._isChanging;
1087 this._isChanging = true;
1088
1089 this._maximum = maximum;
1090
1091 if (maximum < this._value)
1092 this.setValue(maximum - this._extent);
1093 if (maximum < this._minimum) {
1094 this._extent = 0;
1095 this.setMinimum(maximum);
1096 this.setValue(this._maximum);
1097 }
1098 if (maximum < this._minimum + this._extent)
1099 this._extent = this._maximum - this._minimum;
1100 if (maximum < this._value + this._extent)
1101 this._extent = this._maximum - this._value;
1102
1103 this._isChanging = oldIsChanging;
1104 if (!this._isChanging && typeof this.onchange == "function")
1105 this.onchange();
1106 }
1107 };
1108
1109 Range.prototype.getMaximum = function () {
1110 return this._maximum;
1111 };
1112 /*----------------------------------------------------------------------------\
1113 | Slider 1.02 |
1114 |-----------------------------------------------------------------------------|
1115 | Created by Erik Arvidsson |
1116 | (http://webfx.eae.net/contact.html#erik) |
1117 | For WebFX (http://webfx.eae.net/) |
1118 |-----------------------------------------------------------------------------|
1119 | A slider control that degrades to an input control for non supported |
1120 | browsers. |
1121 |-----------------------------------------------------------------------------|
1122 | Copyright (c) 2002, 2003, 2006 Erik Arvidsson |
1123 |-----------------------------------------------------------------------------|
1124 | Licensed under the Apache License, Version 2.0 (the "License"); you may not |
1125 | use this file except in compliance with the License. You may obtain a copy |
1126 | of the License at http://www.apache.org/licenses/LICENSE-2.0 |
1127 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
1128 | Unless required by applicable law or agreed to in writing, software |
1129 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1130 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1131 | License for the specific language governing permissions and limitations |
1132 | under the License. |
1133 |-----------------------------------------------------------------------------|
1134 | Dependencies: timer.js - an OO abstraction of timers |
1135 | range.js - provides the data model for the slider |
1136 | winclassic.css or any other css file describing the look |
1137 |-----------------------------------------------------------------------------|
1138 | 2002-10-14 | Original version released |
1139 | 2003-03-27 | Added a test in the constructor for missing oElement arg |
1140 | 2003-11-27 | Only use mousewheel when focused |
1141 | 2006-05-28 | Changed license to Apache Software License 2.0. |
1142 |-----------------------------------------------------------------------------|
1143 | Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
1144 \----------------------------------------------------------------------------*/
1145
1146 Slider.isSupported = typeof document.createElement != "undefined" &&
1147 typeof document.documentElement != "undefined" &&
1148 typeof document.documentElement.offsetWidth == "number";
1149
1150
1151 function Slider(oElement, oInput, sOrientation) {
1152 if (!oElement) return;
1153 this._orientation = sOrientation || "horizontal";
1154 this._range = new Range();
1155 this._range.setExtent(0);
1156 this._blockIncrement = 10;
1157 this._unitIncrement = 1;
1158 this._timer = new Timer(100);
1159
1160
1161 if (Slider.isSupported && oElement) {
1162
1163 this.document = oElement.ownerDocument || oElement.document;
1164
1165 this.element = oElement;
1166 this.element.slider = this;
1167 this.element.unselectable = "on";
1168
1169 // add class name tag to class name
1170 this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className;
1171
1172 // create line
1173 this.line = this.document.createElement("DIV");
1174 this.line.className = "line";
1175 this.line.unselectable = "on";
1176 this.line.appendChild(this.document.createElement("DIV"));
1177 this.element.appendChild(this.line);
1178
1179 // create handle
1180 this.handle = this.document.createElement("DIV");
1181 this.handle.className = "handle";
1182 this.handle.unselectable = "on";
1183 this.handle.appendChild(this.document.createElement("DIV"));
1184 this.handle.firstChild.appendChild(
1185 this.document.createTextNode(String.fromCharCode(160)));
1186 this.element.appendChild(this.handle);
1187 }
1188
1189 this.input = oInput;
1190
1191 // events
1192 var oThis = this;
1193 this._range.onchange = function () {
1194 oThis.recalculate();
1195 if (typeof oThis.onchange == "function")
1196 oThis.onchange();
1197 };
1198
1199 if (Slider.isSupported && oElement) {
1200 this.element.onfocus = Slider.eventHandlers.onfocus;
1201 this.element.onblur = Slider.eventHandlers.onblur;
1202 this.element.onmousedown = Slider.eventHandlers.onmousedown;
1203 this.element.onmouseover = Slider.eventHandlers.onmouseover;
1204 this.element.onmouseout = Slider.eventHandlers.onmouseout;
1205 this.element.onkeydown = Slider.eventHandlers.onkeydown;
1206 this.element.onkeypress = Slider.eventHandlers.onkeypress;
1207 this.element.onmousewheel = Slider.eventHandlers.onmousewheel;
1208 this.handle.onselectstart =
1209 this.element.onselectstart = function () { return false; };
1210
1211 this._timer.ontimer = function () {
1212 oThis.ontimer();
1213 };
1214
1215 // extra recalculate for ie
1216 window.setTimeout(function() {
1217 oThis.recalculate();
1218 }, 1);
1219 }
1220 else {
1221 this.input.onchange = function (e) {
1222 oThis.setValue(oThis.input.value);
1223 };
1224 }
1225 }
1226
1227 Slider.eventHandlers = {
1228
1229 // helpers to make events a bit easier
1230 getEvent: function (e, el) {
1231 if (!e) {
1232 if (el)
1233 e = el.document.parentWindow.event;
1234 else
1235 e = window.event;
1236 }
1237 if (!e.srcElement) {
1238 var el = e.target;
1239 while (el != null && el.nodeType != 1)
1240 el = el.parentNode;
1241 e.srcElement = el;
1242 }
1243 if (typeof e.offsetX == "undefined") {
1244 e.offsetX = e.layerX;
1245 e.offsetY = e.layerY;
1246 }
1247
1248 return e;
1249 },
1250
1251 getDocument: function (e) {
1252 if (e.target)
1253 return e.target.ownerDocument;
1254 return e.srcElement.document;
1255 },
1256
1257 getSlider: function (e) {
1258 var el = e.target || e.srcElement;
1259 while (el != null && el.slider == null) {
1260 el = el.parentNode;
1261 }
1262 if (el)
1263 return el.slider;
1264 return null;
1265 },
1266
1267 getLine: function (e) {
1268 var el = e.target || e.srcElement;
1269 while (el != null && el.className != "line") {
1270 el = el.parentNode;
1271 }
1272 return el;
1273 },
1274
1275 getHandle: function (e) {
1276 var el = e.target || e.srcElement;
1277 var re = /handle/;
1278 while (el != null && !re.test(el.className)) {
1279 el = el.parentNode;
1280 }
1281 return el;
1282 },
1283 // end helpers
1284
1285 onfocus: function (e) {
1286 var s = this.slider;
1287 s._focused = true;
1288 s.handle.className = "handle hover";
1289 },
1290
1291 onblur: function (e) {
1292 var s = this.slider
1293 s._focused = false;
1294 s.handle.className = "handle";
1295 },
1296
1297 onmouseover: function (e) {
1298 e = Slider.eventHandlers.getEvent(e, this);
1299 var s = this.slider;
1300 if (e.srcElement == s.handle)
1301 s.handle.className = "handle hover";
1302 },
1303
1304 onmouseout: function (e) {
1305 e = Slider.eventHandlers.getEvent(e, this);
1306 var s = this.slider;
1307 if (e.srcElement == s.handle && !s._focused)
1308 s.handle.className = "handle";
1309 },
1310
1311 onmousedown: function (e) {
1312 e = Slider.eventHandlers.getEvent(e, this);
1313 var s = this.slider;
1314 if (s.element.focus)
1315 s.element.focus();
1316
1317 Slider._currentInstance = s;
1318 var doc = s.document;
1319
1320 if (doc.addEventListener) {
1321 doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
1322 doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
1323 }
1324 else if (doc.attachEvent) {
1325 doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
1326 doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
1327 doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
1328 s.element.setCapture();
1329 }
1330
1331 if (Slider.eventHandlers.getHandle(e)) { // start drag
1332 Slider._sliderDragData = {
1333 screenX: e.screenX,
1334 screenY: e.screenY,
1335 dx: e.screenX - s.handle.offsetLeft,
1336 dy: e.screenY - s.handle.offsetTop,
1337 startValue: s.getValue(),
1338 slider: s
1339 };
1340 }
1341 else {
1342 return;
1343 var lineEl = Slider.eventHandlers.getLine(e);
1344 s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
1345 s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
1346 s._increasing = null;
1347 s.ontimer();
1348 }
1349 },
1350
1351 onmousemove: function (e) {
1352 e = Slider.eventHandlers.getEvent(e, this);
1353
1354 if (Slider._sliderDragData) { // drag
1355 var s = Slider._sliderDragData.slider;
1356
1357 var boundSize = s.getMaximum() - s.getMinimum();
1358 var size, pos, reset;
1359
1360 if (s._orientation == "horizontal") {
1361 size = s.element.offsetWidth - s.handle.offsetWidth;
1362 pos = e.screenX - Slider._sliderDragData.dx;
1363 reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;
1364 }
1365 else {
1366 size = s.element.offsetHeight - s.handle.offsetHeight;
1367 pos = s.element.offsetHeight - s.handle.offsetHeight -
1368 (e.screenY - Slider._sliderDragData.dy);
1369 reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;
1370 }
1371 s.setValue(reset ? Slider._sliderDragData.startValue :
1372 s.getMinimum() + boundSize * pos / size);
1373 return false;
1374 }
1375 else {
1376 return;
1377 var s = Slider._currentInstance;
1378 if (s != null) {
1379 var lineEl = Slider.eventHandlers.getLine(e);
1380 s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
1381 s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
1382 }
1383 }
1384
1385 },
1386
1387 onmouseup: function (e) {
1388 e = Slider.eventHandlers.getEvent(e, this);
1389 var s = Slider._currentInstance;
1390 var doc = s.document;
1391 if (doc.removeEventListener) {
1392 doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
1393 doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
1394 }
1395 else if (doc.detachEvent) {
1396 doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
1397 doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
1398 doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
1399 s.element.releaseCapture();
1400 }
1401
1402 if (Slider._sliderDragData) { // end drag
1403 Slider._sliderDragData = null;
1404 }
1405 else {
1406 return;
1407 s._timer.stop();
1408 s._increasing = null;
1409 }
1410 Slider._currentInstance = null;
1411 },
1412
1413 onkeydown: function (e) {
1414 return;
1415 e = Slider.eventHandlers.getEvent(e, this);
1416 //var s = Slider.eventHandlers.getSlider(e);
1417 var s = this.slider;
1418 var kc = e.keyCode;
1419 switch (kc) {
1420 case 33: // page up
1421 s.setValue(s.getValue() + s.getBlockIncrement());
1422 break;
1423 case 34: // page down
1424 s.setValue(s.getValue() - s.getBlockIncrement());
1425 break;
1426 case 35: // end
1427 s.setValue(s.getOrientation() == "horizontal" ?
1428 s.getMaximum() :
1429 s.getMinimum());
1430 break;
1431 case 36: // home
1432 s.setValue(s.getOrientation() == "horizontal" ?
1433 s.getMinimum() :
1434 s.getMaximum());
1435 break;
1436 case 38: // up
1437 case 39: // right
1438 s.setValue(s.getValue() + s.getUnitIncrement());
1439 break;
1440
1441 case 37: // left
1442 case 40: // down
1443 s.setValue(s.getValue() - s.getUnitIncrement());
1444 break;
1445 }
1446
1447 if (kc >= 33 && kc <= 40) {
1448 return false;
1449 }
1450 },
1451
1452 onkeypress: function (e) {
1453 return;
1454 e = Slider.eventHandlers.getEvent(e, this);
1455 var kc = e.keyCode;
1456 if (kc >= 33 && kc <= 40) {
1457 return false;
1458 }
1459 },
1460
1461 onmousewheel: function (e) {
1462 return;
1463 e = Slider.eventHandlers.getEvent(e, this);
1464 var s = this.slider;
1465 if (s._focused) {
1466 s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());
1467 // windows inverts this on horizontal sliders. That does not
1468 // make sense to me
1469 return false;
1470 }
1471 }
1472 };
1473
1474
1475
1476 Slider.prototype.classNameTag = "dynamic-slider-control",
1477
1478 Slider.prototype.setValue = function (v) {
1479 this._range.setValue(v);
1480 this.input.value = this.getValue();
1481 };
1482
1483 Slider.prototype.getValue = function () {
1484 return this._range.getValue();
1485 };
1486
1487 Slider.prototype.setMinimum = function (v) {
1488 this._range.setMinimum(v);
1489 this.input.value = this.getValue();
1490 };
1491
1492 Slider.prototype.getMinimum = function () {
1493 return this._range.getMinimum();
1494 };
1495
1496 Slider.prototype.setMaximum = function (v) {
1497 this._range.setMaximum(v);
1498 this.input.value = this.getValue();
1499 };
1500
1501 Slider.prototype.getMaximum = function () {
1502 return this._range.getMaximum();
1503 };
1504
1505 Slider.prototype.setUnitIncrement = function (v) {
1506 this._unitIncrement = v;
1507 };
1508
1509 Slider.prototype.getUnitIncrement = function () {
1510 return this._unitIncrement;
1511 };
1512
1513 Slider.prototype.setBlockIncrement = function (v) {
1514 this._blockIncrement = v;
1515 };
1516
1517 Slider.prototype.getBlockIncrement = function () {
1518 return this._blockIncrement;
1519 };
1520
1521 Slider.prototype.getOrientation = function () {
1522 return this._orientation;
1523 };
1524
1525 Slider.prototype.setOrientation = function (sOrientation) {
1526 if (sOrientation != this._orientation) {
1527 if (Slider.isSupported && this.element) {
1528 // add class name tag to class name
1529 this.element.className = this.element.className.replace(this._orientation,
1530 sOrientation);
1531 }
1532 this._orientation = sOrientation;
1533 this.recalculate();
1534
1535 }
1536 };
1537
1538 Slider.prototype.recalculate = function() {
1539 if (!Slider.isSupported || !this.element) return;
1540
1541 var w = this.element.offsetWidth;
1542 var h = this.element.offsetHeight;
1543 var hw = this.handle.offsetWidth;
1544 var hh = this.handle.offsetHeight;
1545 var lw = this.line.offsetWidth;
1546 var lh = this.line.offsetHeight;
1547
1548 // this assumes a border-box layout
1549
1550 if (this._orientation == "horizontal") {
1551 this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /
1552 (this.getMaximum() - this.getMinimum()) + "px";
1553 this.handle.style.top = (h - hh) / 2 + "px";
1554
1555 this.line.style.top = (h - lh) / 2 + "px";
1556 this.line.style.left = hw / 2 + "px";
1557 //this.line.style.right = hw / 2 + "px";
1558 this.line.style.width = Math.max(0, w - hw - 2)+ "px";
1559 this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";
1560 }
1561 else {
1562 this.handle.style.left = (w - hw) / 2 + "px";
1563 this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /
1564 (this.getMaximum() - this.getMinimum()) + "px";
1565
1566 this.line.style.left = (w - lw) / 2 + "px";
1567 this.line.style.top = hh / 2 + "px";
1568 this.line.style.height = Math.max(0, h - hh - 2) + "px"; //hard coded border width
1569 //this.line.style.bottom = hh / 2 + "px";
1570 this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px"; //hard coded border width
1571 }
1572 };
1573
1574 Slider.prototype.ontimer = function () {
1575 var hw = this.handle.offsetWidth;
1576 var hh = this.handle.offsetHeight;
1577 var hl = this.handle.offsetLeft;
1578 var ht = this.handle.offsetTop;
1579
1580 if (this._orientation == "horizontal") {
1581 if (this._mouseX > hl + hw &&
1582 (this._increasing == null || this._increasing)) {
1583 this.setValue(this.getValue() + this.getBlockIncrement());
1584 this._increasing = true;
1585 }
1586 else if (this._mouseX < hl &&
1587 (this._increasing == null || !this._increasing)) {
1588 this.setValue(this.getValue() - this.getBlockIncrement());
1589 this._increasing = false;
1590 }
1591 }
1592 else {
1593 if (this._mouseY > ht + hh &&
1594 (this._increasing == null || !this._increasing)) {
1595 this.setValue(this.getValue() - this.getBlockIncrement());
1596 this._increasing = false;
1597 }
1598 else if (this._mouseY < ht &&
1599 (this._increasing == null || this._increasing)) {
1600 this.setValue(this.getValue() + this.getBlockIncrement());
1601 this._increasing = true;
1602 }
1603 }
1604
1605 this._timer.start();
1606 };
1607 /*----------------------------------------------------------------------------\
1608 | Timer Class |
1609 |-----------------------------------------------------------------------------|
1610 | Created by Erik Arvidsson |
1611 | (http://webfx.eae.net/contact.html#erik) |
1612 | For WebFX (http://webfx.eae.net/) |
1613 |-----------------------------------------------------------------------------|
1614 | Object Oriented Encapsulation of setTimeout fires ontimer when the timer |
1615 | is triggered. Does not work in IE 5.00 |
1616 |-----------------------------------------------------------------------------|
1617 | Copyright (c) 2002, 2006 Erik Arvidsson |
1618 |-----------------------------------------------------------------------------|
1619 | Licensed under the Apache License, Version 2.0 (the "License"); you may not |
1620 | use this file except in compliance with the License. You may obtain a copy |
1621 | of the License at http://www.apache.org/licenses/LICENSE-2.0 |
1622 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
1623 | Unless required by applicable law or agreed to in writing, software |
1624 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1625 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1626 | License for the specific language governing permissions and limitations |
1627 | under the License. |
1628 |-----------------------------------------------------------------------------|
1629 | 2002-10-14 | Original version released |
1630 | 2006-05-28 | Changed license to Apache Software License 2.0. |
1631 |-----------------------------------------------------------------------------|
1632 | Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
1633 \----------------------------------------------------------------------------*/
1634
1635 function Timer(nPauseTime) {
1636 this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime;
1637 this._timer = null;
1638 this._isStarted = false;
1639 }
1640
1641 Timer.prototype.start = function () {
1642 if (this.isStarted())
1643 this.stop();
1644 var oThis = this;
1645 this._timer = window.setTimeout(function () {
1646 if (typeof oThis.ontimer == "function")
1647 oThis.ontimer();
1648 }, this._pauseTime);
1649 this._isStarted = false;
1650 };
1651
1652 Timer.prototype.stop = function () {
1653 if (this._timer != null)
1654 window.clearTimeout(this._timer);
1655 this._isStarted = false;
1656 };
1657
1658 Timer.prototype.isStarted = function () {
1659 return this._isStarted;
1660 };
1661
1662 Timer.prototype.getPauseTime = function () {
1663 return this._pauseTime;
1664 };
1665
1666 Timer.prototype.setPauseTime = function (nPauseTime) {
1667 this._pauseTime = nPauseTime;
1668 };
1669 /*
1670
1671 OpenLayers.js -- OpenLayers Map Viewer Library
1672
1673 Copyright (c) 2006-2013 by OpenLayers Contributors
1674 Published under the 2-clause BSD license.
1675 See http://openlayers.org/dev/license.txt for the full text of the license, and http://openlayers.org/dev/authors.txt for full list of contributors.
1676
1677 Includes compressed code under the following licenses:
1678
1679 (For uncompressed versions of the code used, please see the
1680 OpenLayers Github repository: <https://github.com/openlayers/openlayers>)
1681
1682 */
1683
1684 /**
1685 * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
1686 * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
1687 *
1688 * Licensed under the Apache License, Version 2.0 (the "License");
1689 * you may not use this file except in compliance with the License.
1690 * You may obtain a copy of the License at
1691 * http://www.apache.org/licenses/LICENSE-2.0
1692 */
1693
1694 /**
1695 * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
1696 * Copyright (c) 2006, Yahoo! Inc.
1697 * All rights reserved.
1698 *
1699 * Redistribution and use of this software in source and binary forms, with or
1700 * without modification, are permitted provided that the following conditions
1701 * are met:
1702 *
1703 * * Redistributions of source code must retain the above copyright notice,
1704 * this list of conditions and the following disclaimer.
1705 *
1706 * * Redistributions in binary form must reproduce the above copyright notice,
1707 * this list of conditions and the following disclaimer in the documentation
1708 * and/or other materials provided with the distribution.
1709 *
1710 * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
1711 * used to endorse or promote products derived from this software without
1712 * specific prior written permission of Yahoo! Inc.
1713 *
1714 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1715 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1716 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1717 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1718 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1719 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1720 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1721 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1722 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1723 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1724 * POSSIBILITY OF SUCH DAMAGE.
1725 */
1726 var OpenLayers={VERSION_NUMBER:"Release 2.13.1",singleFile:!0,_getScriptLocation:function(){for(var a=/(^|(.*?\/))(OpenLayers[^\/]*?\.js)(\?|$)/,b=document.getElementsByTagName("script"),c,d="",e=0,f=b.length;e<f;e++)if(c=b[e].getAttribute("src"))if(c=c.match(a)){d=c[1];break}return function(){return d}}(),ImgPath:""};OpenLayers.Class=function(){var a=arguments.length,b=arguments[0],c=arguments[a-1],d="function"==typeof c.initialize?c.initialize:function(){b.prototype.initialize.apply(this,arguments)};1<a?(a=[d,b].concat(Array.prototype.slice.call(arguments).slice(1,a-1),c),OpenLayers.inherit.apply(null,a)):d.prototype=c;return d};
1727 OpenLayers.inherit=function(a,b){var c=function(){};c.prototype=b.prototype;a.prototype=new c;var d,e,c=2;for(d=arguments.length;c<d;c++)e=arguments[c],"function"===typeof e&&(e=e.prototype),OpenLayers.Util.extend(a.prototype,e)};OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.extend=function(a,b){a=a||{};if(b){for(var c in b){var d=b[c];void 0!==d&&(a[c]=d)}"function"==typeof window.Event&&b instanceof window.Event||(!b.hasOwnProperty||!b.hasOwnProperty("toString"))||(a.toString=b.toString)}return a};OpenLayers.String={startsWith:function(a,b){return 0==a.indexOf(b)},contains:function(a,b){return-1!=a.indexOf(b)},trim:function(a){return a.replace(/^\s\s*/,"").replace(/\s\s*$/,"")},camelize:function(a){a=a.split("-");for(var b=a[0],c=1,d=a.length;c<d;c++)var e=a[c],b=b+(e.charAt(0).toUpperCase()+e.substring(1));return b},format:function(a,b,c){b||(b=window);return a.replace(OpenLayers.String.tokenRegEx,function(a,e){for(var f,g=e.split(/\.+/),h=0;h<g.length;h++){0==h&&(f=b);if(void 0===f)break;
1728 f=f[g[h]]}"function"==typeof f&&(f=c?f.apply(null,c):f());return"undefined"==typeof f?"undefined":f})},tokenRegEx:/\$\{([\w.]+?)\}/g,numberRegEx:/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,isNumeric:function(a){return OpenLayers.String.numberRegEx.test(a)},numericIf:function(a,b){var c=a;!0===b&&(null!=a&&a.replace)&&(a=a.replace(/^\s*|\s*$/g,""));return OpenLayers.String.isNumeric(a)?parseFloat(a):c}};
1729 OpenLayers.Number={decimalSeparator:".",thousandsSeparator:",",limitSigDigs:function(a,b){var c=0;0<b&&(c=parseFloat(a.toPrecision(b)));return c},format:function(a,b,c,d){b="undefined"!=typeof b?b:0;c="undefined"!=typeof c?c:OpenLayers.Number.thousandsSeparator;d="undefined"!=typeof d?d:OpenLayers.Number.decimalSeparator;null!=b&&(a=parseFloat(a.toFixed(b)));var e=a.toString().split(".");1==e.length&&null==b&&(b=0);a=e[0];if(c)for(var f=/(-?[0-9]+)([0-9]{3})/;f.test(a);)a=a.replace(f,"$1"+c+"$2");
1730 0==b?b=a:(c=1<e.length?e[1]:"0",null!=b&&(c+=Array(b-c.length+1).join("0")),b=a+d+c);return b},zeroPad:function(a,b,c){for(a=a.toString(c||10);a.length<b;)a="0"+a;return a}};
1731 OpenLayers.Function={bind:function(a,b){var c=Array.prototype.slice.apply(arguments,[2]);return function(){var d=c.concat(Array.prototype.slice.apply(arguments,[0]));return a.apply(b,d)}},bindAsEventListener:function(a,b){return function(c){return a.call(b,c||window.event)}},False:function(){return!1},True:function(){return!0},Void:function(){}};
1732 OpenLayers.Array={filter:function(a,b,c){var d=[];if(Array.prototype.filter)d=a.filter(b,c);else{var e=a.length;if("function"!=typeof b)throw new TypeError;for(var f=0;f<e;f++)if(f in a){var g=a[f];b.call(c,g,f,a)&&d.push(g)}}return d}};OpenLayers.Bounds=OpenLayers.Class({left:null,bottom:null,right:null,top:null,centerLonLat:null,initialize:function(a,b,c,d){OpenLayers.Util.isArray(a)&&(d=a[3],c=a[2],b=a[1],a=a[0]);null!=a&&(this.left=OpenLayers.Util.toFloat(a));null!=b&&(this.bottom=OpenLayers.Util.toFloat(b));null!=c&&(this.right=OpenLayers.Util.toFloat(c));null!=d&&(this.top=OpenLayers.Util.toFloat(d))},clone:function(){return new OpenLayers.Bounds(this.left,this.bottom,this.right,this.top)},equals:function(a){var b=!1;null!=
1733 a&&(b=this.left==a.left&&this.right==a.right&&this.top==a.top&&this.bottom==a.bottom);return b},toString:function(){return[this.left,this.bottom,this.right,this.top].join()},toArray:function(a){return!0===a?[this.bottom,this.left,this.top,this.right]:[this.left,this.bottom,this.right,this.top]},toBBOX:function(a,b){null==a&&(a=6);var c=Math.pow(10,a),d=Math.round(this.left*c)/c,e=Math.round(this.bottom*c)/c,f=Math.round(this.right*c)/c,c=Math.round(this.top*c)/c;return!0===b?e+","+d+","+c+","+f:d+
1734 ","+e+","+f+","+c},toGeometry:function(){return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(this.left,this.bottom),new OpenLayers.Geometry.Point(this.right,this.bottom),new OpenLayers.Geometry.Point(this.right,this.top),new OpenLayers.Geometry.Point(this.left,this.top)])])},getWidth:function(){return this.right-this.left},getHeight:function(){return this.top-this.bottom},getSize:function(){return new OpenLayers.Size(this.getWidth(),this.getHeight())},
1735 getCenterPixel:function(){return new OpenLayers.Pixel((this.left+this.right)/2,(this.bottom+this.top)/2)},getCenterLonLat:function(){this.centerLonLat||(this.centerLonLat=new OpenLayers.LonLat((this.left+this.right)/2,(this.bottom+this.top)/2));return this.centerLonLat},scale:function(a,b){null==b&&(b=this.getCenterLonLat());var c,d;"OpenLayers.LonLat"==b.CLASS_NAME?(c=b.lon,d=b.lat):(c=b.x,d=b.y);return new OpenLayers.Bounds((this.left-c)*a+c,(this.bottom-d)*a+d,(this.right-c)*a+c,(this.top-d)*a+
1736 d)},add:function(a,b){if(null==a||null==b)throw new TypeError("Bounds.add cannot receive null values");return new OpenLayers.Bounds(this.left+a,this.bottom+b,this.right+a,this.top+b)},extend:function(a){if(a)switch(a.CLASS_NAME){case "OpenLayers.LonLat":this.extendXY(a.lon,a.lat);break;case "OpenLayers.Geometry.Point":this.extendXY(a.x,a.y);break;case "OpenLayers.Bounds":this.centerLonLat=null;if(null==this.left||a.left<this.left)this.left=a.left;if(null==this.bottom||a.bottom<this.bottom)this.bottom=
1737 a.bottom;if(null==this.right||a.right>this.right)this.right=a.right;if(null==this.top||a.top>this.top)this.top=a.top}},extendXY:function(a,b){this.centerLonLat=null;if(null==this.left||a<this.left)this.left=a;if(null==this.bottom||b<this.bottom)this.bottom=b;if(null==this.right||a>this.right)this.right=a;if(null==this.top||b>this.top)this.top=b},containsLonLat:function(a,b){"boolean"===typeof b&&(b={inclusive:b});b=b||{};var c=this.contains(a.lon,a.lat,b.inclusive),d=b.worldBounds;d&&!c&&(c=d.getWidth(),
1738 d=Math.round((a.lon-(d.left+d.right)/2)/c),c=this.containsLonLat({lon:a.lon-d*c,lat:a.lat},{inclusive:b.inclusive}));return c},containsPixel:function(a,b){return this.contains(a.x,a.y,b)},contains:function(a,b,c){null==c&&(c=!0);if(null==a||null==b)return!1;a=OpenLayers.Util.toFloat(a);b=OpenLayers.Util.toFloat(b);var d=!1;return d=c?a>=this.left&&a<=this.right&&b>=this.bottom&&b<=this.top:a>this.left&&a<this.right&&b>this.bottom&&b<this.top},intersectsBounds:function(a,b){"boolean"===typeof b&&(b=
1739 {inclusive:b});b=b||{};if(b.worldBounds){var c=this.wrapDateLine(b.worldBounds);a=a.wrapDateLine(b.worldBounds)}else c=this;null==b.inclusive&&(b.inclusive=!0);var d=!1,e=c.left==a.right||c.right==a.left||c.top==a.bottom||c.bottom==a.top;if(b.inclusive||!e)var d=a.top>=c.bottom&&a.top<=c.top||c.top>a.bottom&&c.top<a.top,e=a.left>=c.left&&a.left<=c.right||c.left>=a.left&&c.left<=a.right,f=a.right>=c.left&&a.right<=c.right||c.right>=a.left&&c.right<=a.right,d=(a.bottom>=c.bottom&&a.bottom<=c.top||c.bottom>=
1740 a.bottom&&c.bottom<=a.top||d)&&(e||f);if(b.worldBounds&&!d){var g=b.worldBounds,e=g.getWidth(),f=!g.containsBounds(c),g=!g.containsBounds(a);f&&!g?(a=a.add(-e,0),d=c.intersectsBounds(a,{inclusive:b.inclusive})):g&&!f&&(c=c.add(-e,0),d=a.intersectsBounds(c,{inclusive:b.inclusive}))}return d},containsBounds:function(a,b,c){null==b&&(b=!1);null==c&&(c=!0);var d=this.contains(a.left,a.bottom,c),e=this.contains(a.right,a.bottom,c),f=this.contains(a.left,a.top,c);a=this.contains(a.right,a.top,c);return b?
1741 d||e||f||a:d&&e&&f&&a},determineQuadrant:function(a){var b="",c=this.getCenterLonLat(),b=b+(a.lat<c.lat?"b":"t");return b+=a.lon<c.lon?"l":"r"},transform:function(a,b){this.centerLonLat=null;var c=OpenLayers.Projection.transform({x:this.left,y:this.bottom},a,b),d=OpenLayers.Projection.transform({x:this.right,y:this.bottom},a,b),e=OpenLayers.Projection.transform({x:this.left,y:this.top},a,b),f=OpenLayers.Projection.transform({x:this.right,y:this.top},a,b);this.left=Math.min(c.x,e.x);this.bottom=Math.min(c.y,
1742 d.y);this.right=Math.max(d.x,f.x);this.top=Math.max(e.y,f.y);return this},wrapDateLine:function(a,b){b=b||{};var c=b.leftTolerance||0,d=b.rightTolerance||0,e=this.clone();if(a){for(var f=a.getWidth();e.left<a.left&&e.right-d<=a.left;)e=e.add(f,0);for(;e.left+c>=a.right&&e.right>a.right;)e=e.add(-f,0);c=e.left+c;c<a.right&&(c>a.left&&e.right-d>a.right)&&(e=e.add(-f,0))}return e},CLASS_NAME:"OpenLayers.Bounds"});
1743 OpenLayers.Bounds.fromString=function(a,b){var c=a.split(",");return OpenLayers.Bounds.fromArray(c,b)};OpenLayers.Bounds.fromArray=function(a,b){return!0===b?new OpenLayers.Bounds(a[1],a[0],a[3],a[2]):new OpenLayers.Bounds(a[0],a[1],a[2],a[3])};OpenLayers.Bounds.fromSize=function(a){return new OpenLayers.Bounds(0,a.h,a.w,0)};OpenLayers.Bounds.oppositeQuadrant=function(a){var b;b=""+("t"==a.charAt(0)?"b":"t");return b+="l"==a.charAt(1)?"r":"l"};OpenLayers.Element={visible:function(a){return"none"!=OpenLayers.Util.getElement(a).style.display},toggle:function(){for(var a=0,b=arguments.length;a<b;a++){var c=OpenLayers.Util.getElement(arguments[a]),d=OpenLayers.Element.visible(c)?"none":"";c.style.display=d}},remove:function(a){a=OpenLayers.Util.getElement(a);a.parentNode.removeChild(a)},getHeight:function(a){a=OpenLayers.Util.getElement(a);return a.offsetHeight},hasClass:function(a,b){var c=a.className;return!!c&&RegExp("(^|\\s)"+b+"(\\s|$)").test(c)},
1744 addClass:function(a,b){OpenLayers.Element.hasClass(a,b)||(a.className+=(a.className?" ":"")+b);return a},removeClass:function(a,b){var c=a.className;c&&(a.className=OpenLayers.String.trim(c.replace(RegExp("(^|\\s+)"+b+"(\\s+|$)")," ")));return a},toggleClass:function(a,b){OpenLayers.Element.hasClass(a,b)?OpenLayers.Element.removeClass(a,b):OpenLayers.Element.addClass(a,b);return a},getStyle:function(a,b){a=OpenLayers.Util.getElement(a);var c=null;if(a&&a.style){c=a.style[OpenLayers.String.camelize(b)];
1745 c||(document.defaultView&&document.defaultView.getComputedStyle?c=(c=document.defaultView.getComputedStyle(a,null))?c.getPropertyValue(b):null:a.currentStyle&&(c=a.currentStyle[OpenLayers.String.camelize(b)]));var d=["left","top","right","bottom"];window.opera&&(-1!=OpenLayers.Util.indexOf(d,b)&&"static"==OpenLayers.Element.getStyle(a,"position"))&&(c="auto")}return"auto"==c?null:c}};OpenLayers.LonLat=OpenLayers.Class({lon:0,lat:0,initialize:function(a,b){OpenLayers.Util.isArray(a)&&(b=a[1],a=a[0]);this.lon=OpenLayers.Util.toFloat(a);this.lat=OpenLayers.Util.toFloat(b)},toString:function(){return"lon="+this.lon+",lat="+this.lat},toShortString:function(){return this.lon+", "+this.lat},clone:function(){return new OpenLayers.LonLat(this.lon,this.lat)},add:function(a,b){if(null==a||null==b)throw new TypeError("LonLat.add cannot receive null values");return new OpenLayers.LonLat(this.lon+
1746 OpenLayers.Util.toFloat(a),this.lat+OpenLayers.Util.toFloat(b))},equals:function(a){var b=!1;null!=a&&(b=this.lon==a.lon&&this.lat==a.lat||isNaN(this.lon)&&isNaN(this.lat)&&isNaN(a.lon)&&isNaN(a.lat));return b},transform:function(a,b){var c=OpenLayers.Projection.transform({x:this.lon,y:this.lat},a,b);this.lon=c.x;this.lat=c.y;return this},wrapDateLine:function(a){var b=this.clone();if(a){for(;b.lon<a.left;)b.lon+=a.getWidth();for(;b.lon>a.right;)b.lon-=a.getWidth()}return b},CLASS_NAME:"OpenLayers.LonLat"});
1747 OpenLayers.LonLat.fromString=function(a){a=a.split(",");return new OpenLayers.LonLat(a[0],a[1])};OpenLayers.LonLat.fromArray=function(a){var b=OpenLayers.Util.isArray(a);return new OpenLayers.LonLat(b&&a[0],b&&a[1])};OpenLayers.Pixel=OpenLayers.Class({x:0,y:0,initialize:function(a,b){this.x=parseFloat(a);this.y=parseFloat(b)},toString:function(){return"x="+this.x+",y="+this.y},clone:function(){return new OpenLayers.Pixel(this.x,this.y)},equals:function(a){var b=!1;null!=a&&(b=this.x==a.x&&this.y==a.y||isNaN(this.x)&&isNaN(this.y)&&isNaN(a.x)&&isNaN(a.y));return b},distanceTo:function(a){return Math.sqrt(Math.pow(this.x-a.x,2)+Math.pow(this.y-a.y,2))},add:function(a,b){if(null==a||null==b)throw new TypeError("Pixel.add cannot receive null values");
1748 return new OpenLayers.Pixel(this.x+a,this.y+b)},offset:function(a){var b=this.clone();a&&(b=this.add(a.x,a.y));return b},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Size=OpenLayers.Class({w:0,h:0,initialize:function(a,b){this.w=parseFloat(a);this.h=parseFloat(b)},toString:function(){return"w="+this.w+",h="+this.h},clone:function(){return new OpenLayers.Size(this.w,this.h)},equals:function(a){var b=!1;null!=a&&(b=this.w==a.w&&this.h==a.h||isNaN(this.w)&&isNaN(this.h)&&isNaN(a.w)&&isNaN(a.h));return b},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(a){alert(a)},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){},CLASS_NAME:"OpenLayers.Console"};
1749 (function(){for(var a=document.getElementsByTagName("script"),b=0,c=a.length;b<c;++b)if(-1!=a[b].src.indexOf("firebug.js")&&console){OpenLayers.Util.extend(OpenLayers.Console,console);break}})();OpenLayers.Lang={code:null,defaultCode:"en",getCode:function(){OpenLayers.Lang.code||OpenLayers.Lang.setCode();return OpenLayers.Lang.code},setCode:function(a){var b;a||(a="msie"==OpenLayers.BROWSER_NAME?navigator.userLanguage:navigator.language);a=a.split("-");a[0]=a[0].toLowerCase();"object"==typeof OpenLayers.Lang[a[0]]&&(b=a[0]);if(a[1]){var c=a[0]+"-"+a[1].toUpperCase();"object"==typeof OpenLayers.Lang[c]&&(b=c)}b||(OpenLayers.Console.warn("Failed to find OpenLayers.Lang."+a.join("-")+" dictionary, falling back to default language"),
1750 b=OpenLayers.Lang.defaultCode);OpenLayers.Lang.code=b},translate:function(a,b){var c=OpenLayers.Lang[OpenLayers.Lang.getCode()];(c=c&&c[a])||(c=a);b&&(c=OpenLayers.String.format(c,b));return c}};OpenLayers.i18n=OpenLayers.Lang.translate;OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.getElement=function(){for(var a=[],b=0,c=arguments.length;b<c;b++){var d=arguments[b];"string"==typeof d&&(d=document.getElementById(d));if(1==arguments.length)return d;a.push(d)}return a};OpenLayers.Util.isElement=function(a){return!(!a||1!==a.nodeType)};OpenLayers.Util.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)};OpenLayers.Util.removeItem=function(a,b){for(var c=a.length-1;0<=c;c--)a[c]==b&&a.splice(c,1);return a};
1751 OpenLayers.Util.indexOf=function(a,b){if("function"==typeof a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;c<d;c++)if(a[c]==b)return c;return-1};OpenLayers.Util.dotless=/\./g;
1752 OpenLayers.Util.modifyDOMElement=function(a,b,c,d,e,f,g,h){b&&(a.id=b.replace(OpenLayers.Util.dotless,"_"));c&&(a.style.left=c.x+"px",a.style.top=c.y+"px");d&&(a.style.width=d.w+"px",a.style.height=d.h+"px");e&&(a.style.position=e);f&&(a.style.border=f);g&&(a.style.overflow=g);0<=parseFloat(h)&&1>parseFloat(h)?(a.style.filter="alpha(opacity="+100*h+")",a.style.opacity=h):1==parseFloat(h)&&(a.style.filter="",a.style.opacity="")};
1753 OpenLayers.Util.createDiv=function(a,b,c,d,e,f,g,h){var k=document.createElement("div");d&&(k.style.backgroundImage="url("+d+")");a||(a=OpenLayers.Util.createUniqueID("OpenLayersDiv"));e||(e="absolute");OpenLayers.Util.modifyDOMElement(k,a,b,c,e,f,g,h);return k};
1754 OpenLayers.Util.createImage=function(a,b,c,d,e,f,g,h){var k=document.createElement("img");a||(a=OpenLayers.Util.createUniqueID("OpenLayersDiv"));e||(e="relative");OpenLayers.Util.modifyDOMElement(k,a,b,c,e,f,null,g);h&&(k.style.display="none",b=function(){k.style.display="";OpenLayers.Event.stopObservingElement(k)},OpenLayers.Event.observe(k,"load",b),OpenLayers.Event.observe(k,"error",b));k.style.alt=a;k.galleryImg="no";d&&(k.src=d);return k};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;
1755 OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(null==OpenLayers.Util.alphaHackNeeded){var a=navigator.appVersion.split("MSIE"),a=parseFloat(a[1]),b=!1;try{b=!!document.body.filters}catch(c){}OpenLayers.Util.alphaHackNeeded=b&&5.5<=a&&7>a}return OpenLayers.Util.alphaHackNeeded};
1756 OpenLayers.Util.modifyAlphaImageDiv=function(a,b,c,d,e,f,g,h,k){OpenLayers.Util.modifyDOMElement(a,b,c,d,f,null,null,k);b=a.childNodes[0];e&&(b.src=e);OpenLayers.Util.modifyDOMElement(b,a.id+"_innerImage",null,d,"relative",g);OpenLayers.Util.alphaHack()&&("none"!=a.style.display&&(a.style.display="inline-block"),null==h&&(h="scale"),a.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+b.src+"', sizingMethod='"+h+"')",0<=parseFloat(a.style.opacity)&&1>parseFloat(a.style.opacity)&&
1757 (a.style.filter+=" alpha(opacity="+100*a.style.opacity+")"),b.style.filter="alpha(opacity=0)")};OpenLayers.Util.createAlphaImageDiv=function(a,b,c,d,e,f,g,h,k){var l=OpenLayers.Util.createDiv();k=OpenLayers.Util.createImage(null,null,null,null,null,null,null,k);k.className="olAlphaImg";l.appendChild(k);OpenLayers.Util.modifyAlphaImageDiv(l,a,b,c,d,e,f,g,h);return l};OpenLayers.Util.upperCaseObject=function(a){var b={},c;for(c in a)b[c.toUpperCase()]=a[c];return b};
1758 OpenLayers.Util.applyDefaults=function(a,b){a=a||{};var c="function"==typeof window.Event&&b instanceof window.Event,d;for(d in b)if(void 0===a[d]||!c&&b.hasOwnProperty&&b.hasOwnProperty(d)&&!a.hasOwnProperty(d))a[d]=b[d];!c&&(b&&b.hasOwnProperty&&b.hasOwnProperty("toString")&&!a.hasOwnProperty("toString"))&&(a.toString=b.toString);return a};
1759 OpenLayers.Util.getParameterString=function(a){var b=[],c;for(c in a){var d=a[c];if(null!=d&&"function"!=typeof d){if("object"==typeof d&&d.constructor==Array){for(var e=[],f,g=0,h=d.length;g<h;g++)f=d[g],e.push(encodeURIComponent(null===f||void 0===f?"":f));d=e.join(",")}else d=encodeURIComponent(d);b.push(encodeURIComponent(c)+"="+d)}}return b.join("&")};OpenLayers.Util.urlAppend=function(a,b){var c=a;if(b)var d=(a+" ").split(/[?&]/),c=c+(" "===d.pop()?b:d.length?"&"+b:"?"+b);return c};
1760 OpenLayers.Util.getImagesLocation=function(){return OpenLayers.ImgPath||OpenLayers._getScriptLocation()+"img/"};OpenLayers.Util.getImageLocation=function(a){return OpenLayers.Util.getImagesLocation()+a};OpenLayers.Util.Try=function(){for(var a=null,b=0,c=arguments.length;b<c;b++){var d=arguments[b];try{a=d();break}catch(e){}}return a};
1761 OpenLayers.Util.getXmlNodeValue=function(a){var b=null;OpenLayers.Util.Try(function(){b=a.text;b||(b=a.textContent);b||(b=a.firstChild.nodeValue)},function(){b=a.textContent});return b};OpenLayers.Util.mouseLeft=function(a,b){for(var c=a.relatedTarget?a.relatedTarget:a.toElement;c!=b&&null!=c;)c=c.parentNode;return c!=b};OpenLayers.Util.DEFAULT_PRECISION=14;OpenLayers.Util.toFloat=function(a,b){null==b&&(b=OpenLayers.Util.DEFAULT_PRECISION);"number"!==typeof a&&(a=parseFloat(a));return 0===b?a:parseFloat(a.toPrecision(b))};
1762 OpenLayers.Util.rad=function(a){return a*Math.PI/180};OpenLayers.Util.deg=function(a){return 180*a/Math.PI};OpenLayers.Util.VincentyConstants={a:6378137,b:6356752.3142,f:1/298.257223563};
1763 OpenLayers.Util.distVincenty=function(a,b){for(var c=OpenLayers.Util.VincentyConstants,d=c.a,e=c.b,c=c.f,f=OpenLayers.Util.rad(b.lon-a.lon),g=Math.atan((1-c)*Math.tan(OpenLayers.Util.rad(a.lat))),h=Math.atan((1-c)*Math.tan(OpenLayers.Util.rad(b.lat))),k=Math.sin(g),g=Math.cos(g),l=Math.sin(h),h=Math.cos(h),m=f,n=2*Math.PI,p=20;1E-12<Math.abs(m-n)&&0<--p;){var q=Math.sin(m),r=Math.cos(m),s=Math.sqrt(h*q*h*q+(g*l-k*h*r)*(g*l-k*h*r));if(0==s)return 0;var r=k*l+g*h*r,t=Math.atan2(s,r),u=Math.asin(g*h*
1764 q/s),v=Math.cos(u)*Math.cos(u),q=r-2*k*l/v,w=c/16*v*(4+c*(4-3*v)),n=m,m=f+(1-w)*c*Math.sin(u)*(t+w*s*(q+w*r*(-1+2*q*q)))}if(0==p)return NaN;d=v*(d*d-e*e)/(e*e);c=d/1024*(256+d*(-128+d*(74-47*d)));return(e*(1+d/16384*(4096+d*(-768+d*(320-175*d))))*(t-c*s*(q+c/4*(r*(-1+2*q*q)-c/6*q*(-3+4*s*s)*(-3+4*q*q))))).toFixed(3)/1E3};
1765 OpenLayers.Util.destinationVincenty=function(a,b,c){var d=OpenLayers.Util,e=d.VincentyConstants,f=e.a,g=e.b,h=e.f,e=a.lon;a=a.lat;var k=d.rad(b);b=Math.sin(k);k=Math.cos(k);a=(1-h)*Math.tan(d.rad(a));var l=1/Math.sqrt(1+a*a),m=a*l,n=Math.atan2(a,k);a=l*b;for(var p=1-a*a,f=p*(f*f-g*g)/(g*g),q=1+f/16384*(4096+f*(-768+f*(320-175*f))),r=f/1024*(256+f*(-128+f*(74-47*f))),f=c/(g*q),s=2*Math.PI;1E-12<Math.abs(f-s);)var t=Math.cos(2*n+f),u=Math.sin(f),v=Math.cos(f),w=r*u*(t+r/4*(v*(-1+2*t*t)-r/6*t*(-3+4*
1766 u*u)*(-3+4*t*t))),s=f,f=c/(g*q)+w;c=m*u-l*v*k;g=Math.atan2(m*v+l*u*k,(1-h)*Math.sqrt(a*a+c*c));b=Math.atan2(u*b,l*v-m*u*k);k=h/16*p*(4+h*(4-3*p));t=b-(1-k)*h*a*(f+k*u*(t+k*v*(-1+2*t*t)));Math.atan2(a,-c);return new OpenLayers.LonLat(e+d.deg(t),d.deg(g))};
1767 OpenLayers.Util.getParameters=function(a,b){b=b||{};a=null===a||void 0===a?window.location.href:a;var c="";if(OpenLayers.String.contains(a,"?"))var d=a.indexOf("?")+1,c=OpenLayers.String.contains(a,"#")?a.indexOf("#"):a.length,c=a.substring(d,c);for(var d={},c=c.split(/[&;]/),e=0,f=c.length;e<f;++e){var g=c[e].split("=");if(g[0]){var h=g[0];try{h=decodeURIComponent(h)}catch(k){h=unescape(h)}g=(g[1]||"").replace(/\+/g," ");try{g=decodeURIComponent(g)}catch(l){g=unescape(g)}!1!==b.splitArgs&&(g=g.split(","));
1768 1==g.length&&(g=g[0]);d[h]=g}}return d};OpenLayers.Util.lastSeqID=0;OpenLayers.Util.createUniqueID=function(a){a=null==a?"id_":a.replace(OpenLayers.Util.dotless,"_");OpenLayers.Util.lastSeqID+=1;return a+OpenLayers.Util.lastSeqID};OpenLayers.INCHES_PER_UNIT={inches:1,ft:12,mi:63360,m:39.37,km:39370,dd:4374754,yd:36};OpenLayers.INCHES_PER_UNIT["in"]=OpenLayers.INCHES_PER_UNIT.inches;OpenLayers.INCHES_PER_UNIT.degrees=OpenLayers.INCHES_PER_UNIT.dd;OpenLayers.INCHES_PER_UNIT.nmi=1852*OpenLayers.INCHES_PER_UNIT.m;
1769 OpenLayers.METERS_PER_INCH=0.0254000508001016;
1770 OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{Inch:OpenLayers.INCHES_PER_UNIT.inches,Meter:1/OpenLayers.METERS_PER_INCH,Foot:0.3048006096012192/OpenLayers.METERS_PER_INCH,IFoot:0.3048/OpenLayers.METERS_PER_INCH,ClarkeFoot:0.3047972651151/OpenLayers.METERS_PER_INCH,SearsFoot:0.30479947153867626/OpenLayers.METERS_PER_INCH,GoldCoastFoot:0.3047997101815088/OpenLayers.METERS_PER_INCH,IInch:0.0254/OpenLayers.METERS_PER_INCH,MicroInch:2.54E-5/OpenLayers.METERS_PER_INCH,Mil:2.54E-8/OpenLayers.METERS_PER_INCH,
1771 Centimeter:0.01/OpenLayers.METERS_PER_INCH,Kilometer:1E3/OpenLayers.METERS_PER_INCH,Yard:0.9144018288036576/OpenLayers.METERS_PER_INCH,SearsYard:0.914398414616029/OpenLayers.METERS_PER_INCH,IndianYard:0.9143985307444408/OpenLayers.METERS_PER_INCH,IndianYd37:0.91439523/OpenLayers.METERS_PER_INCH,IndianYd62:0.9143988/OpenLayers.METERS_PER_INCH,IndianYd75:0.9143985/OpenLayers.METERS_PER_INCH,IndianFoot:0.30479951/OpenLayers.METERS_PER_INCH,IndianFt37:0.30479841/OpenLayers.METERS_PER_INCH,IndianFt62:0.3047996/
1772 OpenLayers.METERS_PER_INCH,IndianFt75:0.3047995/OpenLayers.METERS_PER_INCH,Mile:1609.3472186944373/OpenLayers.METERS_PER_INCH,IYard:0.9144/OpenLayers.METERS_PER_INCH,IMile:1609.344/OpenLayers.METERS_PER_INCH,NautM:1852/OpenLayers.METERS_PER_INCH,"Lat-66":110943.31648893273/OpenLayers.METERS_PER_INCH,"Lat-83":110946.25736872235/OpenLayers.METERS_PER_INCH,Decimeter:0.1/OpenLayers.METERS_PER_INCH,Millimeter:0.001/OpenLayers.METERS_PER_INCH,Dekameter:10/OpenLayers.METERS_PER_INCH,Decameter:10/OpenLayers.METERS_PER_INCH,
1773 Hectometer:100/OpenLayers.METERS_PER_INCH,GermanMeter:1.0000135965/OpenLayers.METERS_PER_INCH,CaGrid:0.999738/OpenLayers.METERS_PER_INCH,ClarkeChain:20.1166194976/OpenLayers.METERS_PER_INCH,GunterChain:20.11684023368047/OpenLayers.METERS_PER_INCH,BenoitChain:20.116782494375872/OpenLayers.METERS_PER_INCH,SearsChain:20.11676512155/OpenLayers.METERS_PER_INCH,ClarkeLink:0.201166194976/OpenLayers.METERS_PER_INCH,GunterLink:0.2011684023368047/OpenLayers.METERS_PER_INCH,BenoitLink:0.20116782494375873/OpenLayers.METERS_PER_INCH,
1774 SearsLink:0.2011676512155/OpenLayers.METERS_PER_INCH,Rod:5.02921005842012/OpenLayers.METERS_PER_INCH,IntnlChain:20.1168/OpenLayers.METERS_PER_INCH,IntnlLink:0.201168/OpenLayers.METERS_PER_INCH,Perch:5.02921005842012/OpenLayers.METERS_PER_INCH,Pole:5.02921005842012/OpenLayers.METERS_PER_INCH,Furlong:201.1684023368046/OpenLayers.METERS_PER_INCH,Rood:3.778266898/OpenLayers.METERS_PER_INCH,CapeFoot:0.3047972615/OpenLayers.METERS_PER_INCH,Brealey:375/OpenLayers.METERS_PER_INCH,ModAmFt:0.304812252984506/
1775 OpenLayers.METERS_PER_INCH,Fathom:1.8288/OpenLayers.METERS_PER_INCH,"NautM-UK":1853.184/OpenLayers.METERS_PER_INCH,"50kilometers":5E4/OpenLayers.METERS_PER_INCH,"150kilometers":15E4/OpenLayers.METERS_PER_INCH});
1776 OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{mm:OpenLayers.INCHES_PER_UNIT.Meter/1E3,cm:OpenLayers.INCHES_PER_UNIT.Meter/100,dm:100*OpenLayers.INCHES_PER_UNIT.Meter,km:1E3*OpenLayers.INCHES_PER_UNIT.Meter,kmi:OpenLayers.INCHES_PER_UNIT.nmi,fath:OpenLayers.INCHES_PER_UNIT.Fathom,ch:OpenLayers.INCHES_PER_UNIT.IntnlChain,link:OpenLayers.INCHES_PER_UNIT.IntnlLink,"us-in":OpenLayers.INCHES_PER_UNIT.inches,"us-ft":OpenLayers.INCHES_PER_UNIT.Foot,"us-yd":OpenLayers.INCHES_PER_UNIT.Yard,"us-ch":OpenLayers.INCHES_PER_UNIT.GunterChain,
1777 "us-mi":OpenLayers.INCHES_PER_UNIT.Mile,"ind-yd":OpenLayers.INCHES_PER_UNIT.IndianYd37,"ind-ft":OpenLayers.INCHES_PER_UNIT.IndianFt37,"ind-ch":20.11669506/OpenLayers.METERS_PER_INCH});OpenLayers.DOTS_PER_INCH=72;OpenLayers.Util.normalizeScale=function(a){return 1<a?1/a:a};OpenLayers.Util.getResolutionFromScale=function(a,b){var c;a&&(null==b&&(b="degrees"),c=1/(OpenLayers.Util.normalizeScale(a)*OpenLayers.INCHES_PER_UNIT[b]*OpenLayers.DOTS_PER_INCH));return c};
1778 OpenLayers.Util.getScaleFromResolution=function(a,b){null==b&&(b="degrees");return a*OpenLayers.INCHES_PER_UNIT[b]*OpenLayers.DOTS_PER_INCH};
1779 OpenLayers.Util.pagePosition=function(a){var b=[0,0],c=OpenLayers.Util.getViewportElement();if(!a||a==window||a==c)return b;var d=OpenLayers.IS_GECKO&&document.getBoxObjectFor&&"absolute"==OpenLayers.Element.getStyle(a,"position")&&(""==a.style.top||""==a.style.left),e=null;if(a.getBoundingClientRect)a=a.getBoundingClientRect(),e=window.pageYOffset||c.scrollTop,b[0]=a.left+(window.pageXOffset||c.scrollLeft),b[1]=a.top+e;else if(document.getBoxObjectFor&&!d)a=document.getBoxObjectFor(a),c=document.getBoxObjectFor(c),
1780 b[0]=a.screenX-c.screenX,b[1]=a.screenY-c.screenY;else{b[0]=a.offsetLeft;b[1]=a.offsetTop;e=a.offsetParent;if(e!=a)for(;e;)b[0]+=e.offsetLeft,b[1]+=e.offsetTop,e=e.offsetParent;c=OpenLayers.BROWSER_NAME;if("opera"==c||"safari"==c&&"absolute"==OpenLayers.Element.getStyle(a,"position"))b[1]-=document.body.offsetTop;for(e=a.offsetParent;e&&e!=document.body;){b[0]-=e.scrollLeft;if("opera"!=c||"TR"!=e.tagName)b[1]-=e.scrollTop;e=e.offsetParent}}return b};
1781 OpenLayers.Util.getViewportElement=function(){var a=arguments.callee.viewportElement;void 0==a&&(a="msie"==OpenLayers.BROWSER_NAME&&"CSS1Compat"!=document.compatMode?document.body:document.documentElement,arguments.callee.viewportElement=a);return a};
1782 OpenLayers.Util.isEquivalentUrl=function(a,b,c){c=c||{};OpenLayers.Util.applyDefaults(c,{ignoreCase:!0,ignorePort80:!0,ignoreHash:!0,splitArgs:!1});a=OpenLayers.Util.createUrlObject(a,c);b=OpenLayers.Util.createUrlObject(b,c);for(var d in a)if("args"!==d&&a[d]!=b[d])return!1;for(d in a.args){if(a.args[d]!=b.args[d])return!1;delete b.args[d]}for(d in b.args)return!1;return!0};
1783 OpenLayers.Util.createUrlObject=function(a,b){b=b||{};if(!/^\w+:\/\//.test(a)){var c=window.location,d=c.port?":"+c.port:"",d=c.protocol+"//"+c.host.split(":").shift()+d;0===a.indexOf("/")?a=d+a:(c=c.pathname.split("/"),c.pop(),a=d+c.join("/")+"/"+a)}b.ignoreCase&&(a=a.toLowerCase());c=document.createElement("a");c.href=a;d={};d.host=c.host.split(":").shift();d.protocol=c.protocol;d.port=b.ignorePort80?"80"==c.port||"0"==c.port?"":c.port:""==c.port||"0"==c.port?"80":c.port;d.hash=b.ignoreHash||"#"===
1784 c.hash?"":c.hash;var e=c.search;e||(e=a.indexOf("?"),e=-1!=e?a.substr(e):"");d.args=OpenLayers.Util.getParameters(e,{splitArgs:b.splitArgs});d.pathname="/"==c.pathname.charAt(0)?c.pathname:"/"+c.pathname;return d};OpenLayers.Util.removeTail=function(a){var b=null,b=a.indexOf("?"),c=a.indexOf("#");return b=-1==b?-1!=c?a.substr(0,c):a:-1!=c?a.substr(0,Math.min(b,c)):a.substr(0,b)};OpenLayers.IS_GECKO=function(){var a=navigator.userAgent.toLowerCase();return-1==a.indexOf("webkit")&&-1!=a.indexOf("gecko")}();
1785 OpenLayers.CANVAS_SUPPORTED=function(){var a=document.createElement("canvas");return!(!a.getContext||!a.getContext("2d"))}();OpenLayers.BROWSER_NAME=function(){var a="",b=navigator.userAgent.toLowerCase();-1!=b.indexOf("opera")?a="opera":-1!=b.indexOf("msie")?a="msie":-1!=b.indexOf("safari")?a="safari":-1!=b.indexOf("mozilla")&&(a=-1!=b.indexOf("firefox")?"firefox":"mozilla");return a}();OpenLayers.Util.getBrowserName=function(){return OpenLayers.BROWSER_NAME};
1786 OpenLayers.Util.getRenderedDimensions=function(a,b,c){var d,e,f=document.createElement("div");f.style.visibility="hidden";for(var g=c&&c.containerElement?c.containerElement:document.body,h=!1,k=null,l=g;l&&"body"!=l.tagName.toLowerCase();){var m=OpenLayers.Element.getStyle(l,"position");if("absolute"==m){h=!0;break}else if(m&&"static"!=m)break;l=l.parentNode}!h||0!==g.clientHeight&&0!==g.clientWidth||(k=document.createElement("div"),k.style.visibility="hidden",k.style.position="absolute",k.style.overflow=
1787 "visible",k.style.width=document.body.clientWidth+"px",k.style.height=document.body.clientHeight+"px",k.appendChild(f));f.style.position="absolute";b&&(b.w?(d=b.w,f.style.width=d+"px"):b.h&&(e=b.h,f.style.height=e+"px"));c&&c.displayClass&&(f.className=c.displayClass);b=document.createElement("div");b.innerHTML=a;b.style.overflow="visible";if(b.childNodes)for(a=0,c=b.childNodes.length;a<c;a++)b.childNodes[a].style&&(b.childNodes[a].style.overflow="visible");f.appendChild(b);k?g.appendChild(k):g.appendChild(f);
1788 d||(d=parseInt(b.scrollWidth),f.style.width=d+"px");e||(e=parseInt(b.scrollHeight));f.removeChild(b);k?(k.removeChild(f),g.removeChild(k)):g.removeChild(f);return new OpenLayers.Size(d,e)};
1789 OpenLayers.Util.getScrollbarWidth=function(){var a=OpenLayers.Util._scrollbarWidth;if(null==a){var b=null,c=null,b=a=0,b=document.createElement("div");b.style.position="absolute";b.style.top="-1000px";b.style.left="-1000px";b.style.width="100px";b.style.height="50px";b.style.overflow="hidden";c=document.createElement("div");c.style.width="100%";c.style.height="200px";b.appendChild(c);document.body.appendChild(b);a=c.offsetWidth;b.style.overflow="scroll";b=c.offsetWidth;document.body.removeChild(document.body.lastChild);
1790 OpenLayers.Util._scrollbarWidth=a-b;a=OpenLayers.Util._scrollbarWidth}return a};
1791 OpenLayers.Util.getFormattedLonLat=function(a,b,c){c||(c="dms");a=(a+540)%360-180;var d=Math.abs(a),e=Math.floor(d),f=d=(d-e)/(1/60),d=Math.floor(d),f=Math.round(10*((f-d)/(1/60))),f=f/10;60<=f&&(f-=60,d+=1,60<=d&&(d-=60,e+=1));10>e&&(e="0"+e);e+="\u00b0";0<=c.indexOf("dm")&&(10>d&&(d="0"+d),e+=d+"'",0<=c.indexOf("dms")&&(10>f&&(f="0"+f),e+=f+'"'));return e="lon"==b?e+(0>a?OpenLayers.i18n("W"):OpenLayers.i18n("E")):e+(0>a?OpenLayers.i18n("S"):OpenLayers.i18n("N"))};OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:!1,initialize:function(a){OpenLayers.Util.extend(this,a);this.options=a},destroy:function(){},read:function(a){throw Error("Read not implemented.");},write:function(a){throw Error("Write not implemented.");},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Format.CSWGetRecords=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Format.CSWGetRecords.DEFAULTS);var b=OpenLayers.Format.CSWGetRecords["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported CSWGetRecords version: "+a.version;return new b(a)};OpenLayers.Format.CSWGetRecords.DEFAULTS={version:"2.0.2"};OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:!1,displayClass:"",title:"",autoActivate:!1,active:null,handlerOptions:null,handler:null,eventListeners:null,events:null,initialize:function(a){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,a);this.events=new OpenLayers.Events(this);if(this.eventListeners instanceof Object)this.events.on(this.eventListeners);null==this.id&&(this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+
1792 "_"))},destroy:function(){this.events&&(this.eventListeners&&this.events.un(this.eventListeners),this.events.destroy(),this.events=null);this.eventListeners=null;this.handler&&(this.handler.destroy(),this.handler=null);if(this.handlers){for(var a in this.handlers)this.handlers.hasOwnProperty(a)&&"function"==typeof this.handlers[a].destroy&&this.handlers[a].destroy();this.handlers=null}this.map&&(this.map.removeControl(this),this.map=null);this.div=null},setMap:function(a){this.map=a;this.handler&&
1793 this.handler.setMap(a)},draw:function(a){null==this.div&&(this.div=OpenLayers.Util.createDiv(this.id),this.div.className=this.displayClass,this.allowSelection||(this.div.className+=" olControlNoSelect",this.div.setAttribute("unselectable","on",0),this.div.onselectstart=OpenLayers.Function.False),""!=this.title&&(this.div.title=this.title));null!=a&&(this.position=a.clone());this.moveTo(this.position);return this.div},moveTo:function(a){null!=a&&null!=this.div&&(this.div.style.left=a.x+"px",this.div.style.top=
1794 a.y+"px")},activate:function(){if(this.active)return!1;this.handler&&this.handler.activate();this.active=!0;this.map&&OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");this.events.triggerEvent("activate");return!0},deactivate:function(){return this.active?(this.handler&&this.handler.deactivate(),this.active=!1,this.map&&OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active"),this.events.triggerEvent("deactivate"),
1795 !0):!1},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Event={observers:!1,KEY_SPACE:32,KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(a){return a.target||a.srcElement},isSingleTouch:function(a){return a.touches&&1==a.touches.length},isMultiTouch:function(a){return a.touches&&1<a.touches.length},isLeftClick:function(a){return a.which&&1==a.which||a.button&&1==a.button},isRightClick:function(a){return a.which&&3==a.which||a.button&&2==a.button},stop:function(a,
1796 b){b||OpenLayers.Event.preventDefault(a);a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},preventDefault:function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},findElement:function(a,b){for(var c=OpenLayers.Event.element(a);c.parentNode&&(!c.tagName||c.tagName.toUpperCase()!=b.toUpperCase());)c=c.parentNode;return c},observe:function(a,b,c,d){a=OpenLayers.Util.getElement(a);d=d||!1;"keypress"==b&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||a.attachEvent)&&(b="keydown");
1797 this.observers||(this.observers={});if(!a._eventCacheID){var e="eventCacheID_";a.id&&(e=a.id+"_"+e);a._eventCacheID=OpenLayers.Util.createUniqueID(e)}e=a._eventCacheID;this.observers[e]||(this.observers[e]=[]);this.observers[e].push({element:a,name:b,observer:c,useCapture:d});a.addEventListener?a.addEventListener(b,c,d):a.attachEvent&&a.attachEvent("on"+b,c)},stopObservingElement:function(a){a=OpenLayers.Util.getElement(a)._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[a])},
1798 _removeElementObservers:function(a){if(a)for(var b=a.length-1;0<=b;b--){var c=a[b];OpenLayers.Event.stopObserving.apply(this,[c.element,c.name,c.observer,c.useCapture])}},stopObserving:function(a,b,c,d){d=d||!1;a=OpenLayers.Util.getElement(a);var e=a._eventCacheID;"keypress"==b&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||a.detachEvent)&&(b="keydown");var f=!1,g=OpenLayers.Event.observers[e];if(g)for(var h=0;!f&&h<g.length;){var k=g[h];if(k.name==b&&k.observer==c&&k.useCapture==d){g.splice(h,
1799 1);0==g.length&&delete OpenLayers.Event.observers[e];f=!0;break}h++}f&&(a.removeEventListener?a.removeEventListener(b,c,d):a&&a.detachEvent&&a.detachEvent("on"+b,c));return f},unloadCache:function(){if(OpenLayers.Event&&OpenLayers.Event.observers){for(var a in OpenLayers.Event.observers)OpenLayers.Event._removeElementObservers.apply(this,[OpenLayers.Event.observers[a]]);OpenLayers.Event.observers=!1}},CLASS_NAME:"OpenLayers.Event"};
1800 OpenLayers.Event.observe(window,"unload",OpenLayers.Event.unloadCache,!1);
1801 OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:"mouseover mouseout mousedown mouseup mousemove click dblclick rightclick dblrightclick resize focus blur touchstart touchmove touchend keydown".split(" "),listeners:null,object:null,element:null,eventHandler:null,fallThrough:null,includeXY:!1,extensions:null,extensionCount:null,clearMouseListener:null,initialize:function(a,b,c,d,e){OpenLayers.Util.extend(this,e);this.object=a;this.fallThrough=d;this.listeners={};this.extensions={};this.extensionCount=
1802 {};this._msTouches=[];null!=b&&this.attachToElement(b)},destroy:function(){for(var a in this.extensions)"boolean"!==typeof this.extensions[a]&&this.extensions[a].destroy();this.extensions=null;this.element&&(OpenLayers.Event.stopObservingElement(this.element),this.element.hasScrollEvent&&OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener));this.eventHandler=this.fallThrough=this.object=this.listeners=this.element=null},addEventType:function(a){},attachToElement:function(a){this.element?
1803 OpenLayers.Event.stopObservingElement(this.element):(this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this),this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this));this.element=a;for(var b=!!window.navigator.msMaxTouchPoints,c,d=0,e=this.BROWSER_EVENTS.length;d<e;d++)c=this.BROWSER_EVENTS[d],OpenLayers.Event.observe(a,c,this.eventHandler),b&&0===c.indexOf("touch")&&this.addMsTouchListener(a,c,this.eventHandler);OpenLayers.Event.observe(a,"dragstart",
1804 OpenLayers.Event.stop)},on:function(a){for(var b in a)"scope"!=b&&a.hasOwnProperty(b)&&this.register(b,a.scope,a[b])},register:function(a,b,c,d){a in OpenLayers.Events&&!this.extensions[a]&&(this.extensions[a]=new OpenLayers.Events[a](this));if(null!=c){null==b&&(b=this.object);var e=this.listeners[a];e||(e=[],this.listeners[a]=e,this.extensionCount[a]=0);b={obj:b,func:c};d?(e.splice(this.extensionCount[a],0,b),"object"===typeof d&&d.extension&&this.extensionCount[a]++):e.push(b)}},registerPriority:function(a,
1805 b,c){this.register(a,b,c,!0)},un:function(a){for(var b in a)"scope"!=b&&a.hasOwnProperty(b)&&this.unregister(b,a.scope,a[b])},unregister:function(a,b,c){null==b&&(b=this.object);a=this.listeners[a];if(null!=a)for(var d=0,e=a.length;d<e;d++)if(a[d].obj==b&&a[d].func==c){a.splice(d,1);break}},remove:function(a){null!=this.listeners[a]&&(this.listeners[a]=[])},triggerEvent:function(a,b){var c=this.listeners[a];if(c&&0!=c.length){null==b&&(b={});b.object=this.object;b.element=this.element;b.type||(b.type=
1806 a);for(var c=c.slice(),d,e=0,f=c.length;e<f&&(d=c[e],d=d.func.apply(d.obj,[b]),void 0==d||!1!=d);e++);this.fallThrough||OpenLayers.Event.stop(b,!0);return d}},handleBrowserEvent:function(a){var b=a.type,c=this.listeners[b];if(c&&0!=c.length){if((c=a.touches)&&c[0]){for(var d=0,e=0,f=c.length,g,h=0;h<f;++h)g=this.getTouchClientXY(c[h]),d+=g.clientX,e+=g.clientY;a.clientX=d/f;a.clientY=e/f}this.includeXY&&(a.xy=this.getMousePosition(a));this.triggerEvent(b,a)}},getTouchClientXY:function(a){var b=window.olMockWin||
1807 window,c=b.pageXOffset,b=b.pageYOffset,d=a.clientX,e=a.clientY;if(0===a.pageY&&Math.floor(e)>Math.floor(a.pageY)||0===a.pageX&&Math.floor(d)>Math.floor(a.pageX))d-=c,e-=b;else if(e<a.pageY-b||d<a.pageX-c)d=a.pageX-c,e=a.pageY-b;a.olClientX=d;a.olClientY=e;return{clientX:d,clientY:e}},clearMouseCache:function(){this.element.scrolls=null;this.element.lefttop=null;this.element.offsets=null},getMousePosition:function(a){this.includeXY?this.element.hasScrollEvent||(OpenLayers.Event.observe(window,"scroll",
1808 this.clearMouseListener),this.element.hasScrollEvent=!0):this.clearMouseCache();if(!this.element.scrolls){var b=OpenLayers.Util.getViewportElement();this.element.scrolls=[window.pageXOffset||b.scrollLeft,window.pageYOffset||b.scrollTop]}this.element.lefttop||(this.element.lefttop=[document.documentElement.clientLeft||0,document.documentElement.clientTop||0]);this.element.offsets||(this.element.offsets=OpenLayers.Util.pagePosition(this.element));return new OpenLayers.Pixel(a.clientX+this.element.scrolls[0]-
1809 this.element.offsets[0]-this.element.lefttop[0],a.clientY+this.element.scrolls[1]-this.element.offsets[1]-this.element.lefttop[1])},addMsTouchListener:function(a,b,c){function d(a){c(OpenLayers.Util.applyDefaults({stopPropagation:function(){for(var a=e.length-1;0<=a;--a)e[a].stopPropagation()},preventDefault:function(){for(var a=e.length-1;0<=a;--a)e[a].preventDefault()},type:b},a))}var e=this._msTouches;switch(b){case "touchstart":return this.addMsTouchListenerStart(a,b,d);case "touchend":return this.addMsTouchListenerEnd(a,
1810 b,d);case "touchmove":return this.addMsTouchListenerMove(a,b,d);default:throw"Unknown touch event type";}},addMsTouchListenerStart:function(a,b,c){var d=this._msTouches;OpenLayers.Event.observe(a,"MSPointerDown",function(a){for(var b=!1,g=0,h=d.length;g<h;++g)if(d[g].pointerId==a.pointerId){b=!0;break}b||d.push(a);a.touches=d.slice();c(a)});OpenLayers.Event.observe(a,"MSPointerUp",function(a){for(var b=0,c=d.length;b<c;++b)if(d[b].pointerId==a.pointerId){d.splice(b,1);break}})},addMsTouchListenerMove:function(a,
1811 b,c){var d=this._msTouches;OpenLayers.Event.observe(a,"MSPointerMove",function(a){if(a.pointerType!=a.MSPOINTER_TYPE_MOUSE||0!=a.buttons)if(1!=d.length||d[0].pageX!=a.pageX||d[0].pageY!=a.pageY){for(var b=0,g=d.length;b<g;++b)if(d[b].pointerId==a.pointerId){d[b]=a;break}a.touches=d.slice();c(a)}})},addMsTouchListenerEnd:function(a,b,c){var d=this._msTouches;OpenLayers.Event.observe(a,"MSPointerUp",function(a){for(var b=0,g=d.length;b<g;++b)if(d[b].pointerId==a.pointerId){d.splice(b,1);break}a.touches=
1812 d.slice();c(a)})},CLASS_NAME:"OpenLayers.Events"});OpenLayers.Events.buttonclick=OpenLayers.Class({target:null,events:"mousedown mouseup click dblclick touchstart touchmove touchend keydown".split(" "),startRegEx:/^mousedown|touchstart$/,cancelRegEx:/^touchmove$/,completeRegEx:/^mouseup|touchend$/,initialize:function(a){this.target=a;for(a=this.events.length-1;0<=a;--a)this.target.register(this.events[a],this,this.buttonClick,{extension:!0})},destroy:function(){for(var a=this.events.length-1;0<=a;--a)this.target.unregister(this.events[a],this,this.buttonClick);
1813 delete this.target},getPressedButton:function(a){var b=3,c;do{if(OpenLayers.Element.hasClass(a,"olButton")){c=a;break}a=a.parentNode}while(0<--b&&a);return c},ignore:function(a){var b=3,c=!1;do{if("a"===a.nodeName.toLowerCase()){c=!0;break}a=a.parentNode}while(0<--b&&a);return c},buttonClick:function(a){var b=!0,c=OpenLayers.Event.element(a);if(c&&(OpenLayers.Event.isLeftClick(a)||!~a.type.indexOf("mouse")))if(c=this.getPressedButton(c)){if("keydown"===a.type)switch(a.keyCode){case OpenLayers.Event.KEY_RETURN:case OpenLayers.Event.KEY_SPACE:this.target.triggerEvent("buttonclick",
1814 {buttonElement:c}),OpenLayers.Event.stop(a),b=!1}else if(this.startEvt){if(this.completeRegEx.test(a.type)){var b=OpenLayers.Util.pagePosition(c),d=OpenLayers.Util.getViewportElement(),e=window.pageYOffset||d.scrollTop;b[0]-=window.pageXOffset||d.scrollLeft;b[1]-=e;this.target.triggerEvent("buttonclick",{buttonElement:c,buttonXY:{x:this.startEvt.clientX-b[0],y:this.startEvt.clientY-b[1]}})}this.cancelRegEx.test(a.type)&&delete this.startEvt;OpenLayers.Event.stop(a);b=!1}this.startRegEx.test(a.type)&&
1815 (this.startEvt=a,OpenLayers.Event.stop(a),b=!1)}else b=!this.ignore(OpenLayers.Event.element(a)),delete this.startEvt;return b}});OpenLayers.Util=OpenLayers.Util||{};
1816 OpenLayers.Util.vendorPrefix=function(){function a(a){return a?a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()}).replace(/^ms-/,"-ms-"):null}function b(a,b){if(void 0===g[b]){var c,e=0,f=d.length,p="undefined"!==typeof a.cssText;for(g[b]=null;e<f;e++)if((c=d[e])?(p||(c=c.toLowerCase()),c=c+b.charAt(0).toUpperCase()+b.slice(1)):c=b,void 0!==a[c]){g[b]=c;break}}return g[b]}function c(a){return b(e,a)}var d=["","O","ms","Moz","Webkit"],e=document.createElement("div").style,f={},g={};return{css:function(b){if(void 0===
1817 f[b]){var d=b.replace(/(-[\s\S])/g,function(a){return a.charAt(1).toUpperCase()}),d=c(d);f[b]=a(d)}return f[b]},js:b,style:c,cssCache:f,jsCache:g}}();OpenLayers.Animation=function(a){var b=OpenLayers.Util.vendorPrefix.js(a,"requestAnimationFrame"),c=!!b,d=function(){var c=a[b]||function(b,c){a.setTimeout(b,16)};return function(b,d){c.apply(a,[b,d])}}(),e=0,f={};return{isNative:c,requestFrame:d,start:function(a,b,c){b=0<b?b:Number.POSITIVE_INFINITY;var l=++e,m=+new Date;f[l]=function(){f[l]&&+new Date-m<=b?(a(),f[l]&&d(f[l],c)):delete f[l]};d(f[l],c);return l},stop:function(a){delete f[a]}}}(window);OpenLayers.Tween=OpenLayers.Class({easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,minFrameRate:null,startTime:null,animationId:null,playing:!1,initialize:function(a){this.easing=a?a:OpenLayers.Easing.Expo.easeOut},start:function(a,b,c,d){this.playing=!0;this.begin=a;this.finish=b;this.duration=c;this.callbacks=d.callbacks;this.minFrameRate=d.minFrameRate||30;this.time=0;this.startTime=(new Date).getTime();OpenLayers.Animation.stop(this.animationId);this.animationId=null;
1818 this.callbacks&&this.callbacks.start&&this.callbacks.start.call(this,this.begin);this.animationId=OpenLayers.Animation.start(OpenLayers.Function.bind(this.play,this))},stop:function(){this.playing&&(this.callbacks&&this.callbacks.done&&this.callbacks.done.call(this,this.finish),OpenLayers.Animation.stop(this.animationId),this.animationId=null,this.playing=!1)},play:function(){var a={},b;for(b in this.begin){var c=this.begin[b],d=this.finish[b];if(null==c||null==d||isNaN(c)||isNaN(d))throw new TypeError("invalid value for Tween");
1819 a[b]=this.easing.apply(this,[this.time,c,d-c,this.duration])}this.time++;this.callbacks&&this.callbacks.eachStep&&((new Date).getTime()-this.startTime)/this.time<=1E3/this.minFrameRate&&this.callbacks.eachStep.call(this,a);this.time>this.duration&&this.stop()},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(a,b,c,d){return c*a/d+b},easeOut:function(a,b,c,d){return c*a/d+b},easeInOut:function(a,b,c,d){return c*a/d+b},CLASS_NAME:"OpenLayers.Easing.Linear"};
1820 OpenLayers.Easing.Expo={easeIn:function(a,b,c,d){return 0==a?b:c*Math.pow(2,10*(a/d-1))+b},easeOut:function(a,b,c,d){return a==d?b+c:c*(-Math.pow(2,-10*a/d)+1)+b},easeInOut:function(a,b,c,d){return 0==a?b:a==d?b+c:1>(a/=d/2)?c/2*Math.pow(2,10*(a-1))+b:c/2*(-Math.pow(2,-10*--a)+2)+b},CLASS_NAME:"OpenLayers.Easing.Expo"};
1821 OpenLayers.Easing.Quad={easeIn:function(a,b,c,d){return c*(a/=d)*a+b},easeOut:function(a,b,c,d){return-c*(a/=d)*(a-2)+b},easeInOut:function(a,b,c,d){return 1>(a/=d/2)?c/2*a*a+b:-c/2*(--a*(a-2)-1)+b},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,titleRegEx:/\+title=[^\+]*/,initialize:function(a,b){OpenLayers.Util.extend(this,b);this.projCode=a;"object"==typeof Proj4js&&(this.proj=new Proj4js.Proj(a))},getCode:function(){return this.proj?this.proj.srsCode:this.projCode},getUnits:function(){return this.proj?this.proj.units:null},toString:function(){return this.getCode()},equals:function(a){var b=!1;a&&(a instanceof OpenLayers.Projection||(a=new OpenLayers.Projection(a)),"object"==
1822 typeof Proj4js&&this.proj.defData&&a.proj.defData?b=this.proj.defData.replace(this.titleRegEx,"")==a.proj.defData.replace(this.titleRegEx,""):a.getCode&&(b=this.getCode(),a=a.getCode(),b=b==a||!!OpenLayers.Projection.transforms[b]&&OpenLayers.Projection.transforms[b][a]===OpenLayers.Projection.nullTransform));return b},destroy:function(){delete this.proj;delete this.projCode},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};
1823 OpenLayers.Projection.defaults={"EPSG:4326":{units:"degrees",maxExtent:[-180,-90,180,90],yx:!0},"CRS:84":{units:"degrees",maxExtent:[-180,-90,180,90]},"EPSG:900913":{units:"m",maxExtent:[-2.003750834E7,-2.003750834E7,2.003750834E7,2.003750834E7]}};
1824 OpenLayers.Projection.addTransform=function(a,b,c){if(c===OpenLayers.Projection.nullTransform){var d=OpenLayers.Projection.defaults[a];d&&!OpenLayers.Projection.defaults[b]&&(OpenLayers.Projection.defaults[b]=d)}OpenLayers.Projection.transforms[a]||(OpenLayers.Projection.transforms[a]={});OpenLayers.Projection.transforms[a][b]=c};
1825 OpenLayers.Projection.transform=function(a,b,c){if(b&&c)if(b instanceof OpenLayers.Projection||(b=new OpenLayers.Projection(b)),c instanceof OpenLayers.Projection||(c=new OpenLayers.Projection(c)),b.proj&&c.proj)a=Proj4js.transform(b.proj,c.proj,a);else{b=b.getCode();c=c.getCode();var d=OpenLayers.Projection.transforms;if(d[b]&&d[b][c])d[b][c](a)}return a};OpenLayers.Projection.nullTransform=function(a){return a};
1826 (function(){function a(a){a.x=180*a.x/d;a.y=180/Math.PI*(2*Math.atan(Math.exp(a.y/d*Math.PI))-Math.PI/2);return a}function b(a){a.x=a.x*d/180;var b=Math.log(Math.tan((90+a.y)*Math.PI/360))/Math.PI*d;a.y=Math.max(-2.003750834E7,Math.min(b,2.003750834E7));return a}function c(c,d){var e=OpenLayers.Projection.addTransform,f=OpenLayers.Projection.nullTransform,g,p,q,r,s;g=0;for(p=d.length;g<p;++g)for(q=d[g],e(c,q,b),e(q,c,a),s=g+1;s<p;++s)r=d[s],e(q,r,f),e(r,q,f)}var d=2.003750834E7,e=["EPSG:900913","EPSG:3857",
1827 "EPSG:102113","EPSG:102100"],f=["CRS:84","urn:ogc:def:crs:EPSG:6.6:4326","EPSG:4326"],g;for(g=e.length-1;0<=g;--g)c(e[g],f);for(g=f.length-1;0<=g;--g)c(f[g],e)})();OpenLayers.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1E3},id:null,fractionalZoom:!1,events:null,allOverlays:!1,div:null,dragging:!1,size:null,viewPortDiv:null,layerContainerOrigin:null,layerContainerDiv:null,layers:null,controls:null,popups:null,baseLayer:null,center:null,resolution:null,zoom:0,panRatio:1.5,options:null,tileSize:null,projection:"EPSG:4326",units:null,resolutions:null,maxResolution:null,minResolution:null,maxScale:null,minScale:null,
1828 maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:!1,autoUpdateSize:!0,eventListeners:null,panTween:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,zoomTween:null,zoomMethod:OpenLayers.Easing.Quad.easeOut,zoomDuration:20,paddingForPopups:null,layerContainerOriginPx:null,minPx:null,maxPx:null,initialize:function(a,b){1===arguments.length&&"object"===typeof a&&(a=(b=a)&&b.div);this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,
1829 OpenLayers.Map.TILE_HEIGHT);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()+"theme/default/style.css";this.options=OpenLayers.Util.extend({},b);OpenLayers.Util.extend(this,b);OpenLayers.Util.applyDefaults(this,OpenLayers.Projection.defaults[this.projection instanceof OpenLayers.Projection?this.projection.projCode:this.projection]);!this.maxExtent||this.maxExtent instanceof OpenLayers.Bounds||(this.maxExtent=new OpenLayers.Bounds(this.maxExtent));
1830 !this.minExtent||this.minExtent instanceof OpenLayers.Bounds||(this.minExtent=new OpenLayers.Bounds(this.minExtent));!this.restrictedExtent||this.restrictedExtent instanceof OpenLayers.Bounds||(this.restrictedExtent=new OpenLayers.Bounds(this.restrictedExtent));!this.center||this.center instanceof OpenLayers.LonLat||(this.center=new OpenLayers.LonLat(this.center));this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(a);this.div||(this.div=document.createElement("div"),
1831 this.div.style.height="1px",this.div.style.width="1px");OpenLayers.Element.addClass(this.div,"olMap");var c=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(c,null,null,null,"relative",null,"hidden");this.viewPortDiv.style.width="100%";this.viewPortDiv.style.height="100%";this.viewPortDiv.className="olMapViewport";this.div.appendChild(this.viewPortDiv);this.events=new OpenLayers.Events(this,this.viewPortDiv,null,this.fallThrough,{includeXY:!0});OpenLayers.TileManager&&null!==
1832 this.tileManager&&(this.tileManager instanceof OpenLayers.TileManager||(this.tileManager=new OpenLayers.TileManager(this.tileManager)),this.tileManager.addMap(this));c=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(c);this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE.Popup-1;this.layerContainerOriginPx={x:0,y:0};this.applyTransform();this.viewPortDiv.appendChild(this.layerContainerDiv);this.updateSize();if(this.eventListeners instanceof Object)this.events.on(this.eventListeners);
1833 !0===this.autoUpdateSize&&(this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this),OpenLayers.Event.observe(window,"resize",this.updateSizeDestroy));if(this.theme){for(var c=!0,d=document.getElementsByTagName("link"),e=0,f=d.length;e<f;++e)if(OpenLayers.Util.isEquivalentUrl(d.item(e).href,this.theme)){c=!1;break}c&&(c=document.createElement("link"),c.setAttribute("rel","stylesheet"),c.setAttribute("type","text/css"),c.setAttribute("href",this.theme),document.getElementsByTagName("head")[0].appendChild(c))}null==
1834 this.controls&&(this.controls=[],null!=OpenLayers.Control&&(OpenLayers.Control.Navigation?this.controls.push(new OpenLayers.Control.Navigation):OpenLayers.Control.TouchNavigation&&this.controls.push(new OpenLayers.Control.TouchNavigation),OpenLayers.Control.Zoom?this.controls.push(new OpenLayers.Control.Zoom):OpenLayers.Control.PanZoom&&this.controls.push(new OpenLayers.Control.PanZoom),OpenLayers.Control.ArgParser&&this.controls.push(new OpenLayers.Control.ArgParser),OpenLayers.Control.Attribution&&
1835 this.controls.push(new OpenLayers.Control.Attribution)));e=0;for(f=this.controls.length;e<f;e++)this.addControlToMap(this.controls[e]);this.popups=[];this.unloadDestroy=OpenLayers.Function.bind(this.destroy,this);OpenLayers.Event.observe(window,"unload",this.unloadDestroy);b&&b.layers&&(delete this.center,delete this.zoom,this.addLayers(b.layers),b.center&&!this.getCenter()&&this.setCenter(b.center,b.zoom));this.panMethod&&(this.panTween=new OpenLayers.Tween(this.panMethod));this.zoomMethod&&this.applyTransform.transform&&
1836 (this.zoomTween=new OpenLayers.Tween(this.zoomMethod))},getViewport:function(){return this.viewPortDiv},render:function(a){this.div=OpenLayers.Util.getElement(a);OpenLayers.Element.addClass(this.div,"olMap");this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);this.div.appendChild(this.viewPortDiv);this.updateSize()},unloadDestroy:null,updateSizeDestroy:null,destroy:function(){if(!this.unloadDestroy)return!1;this.panTween&&(this.panTween.stop(),this.panTween=null);this.zoomTween&&(this.zoomTween.stop(),
1837 this.zoomTween=null);OpenLayers.Event.stopObserving(window,"unload",this.unloadDestroy);this.unloadDestroy=null;this.updateSizeDestroy&&OpenLayers.Event.stopObserving(window,"resize",this.updateSizeDestroy);this.paddingForPopups=null;if(null!=this.controls){for(var a=this.controls.length-1;0<=a;--a)this.controls[a].destroy();this.controls=null}if(null!=this.layers){for(a=this.layers.length-1;0<=a;--a)this.layers[a].destroy(!1);this.layers=null}this.viewPortDiv&&this.viewPortDiv.parentNode&&this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
1838 this.viewPortDiv=null;this.tileManager&&(this.tileManager.removeMap(this),this.tileManager=null);this.eventListeners&&(this.events.un(this.eventListeners),this.eventListeners=null);this.events.destroy();this.options=this.events=null},setOptions:function(a){var b=this.minPx&&a.restrictedExtent!=this.restrictedExtent;OpenLayers.Util.extend(this,a);b&&this.moveTo(this.getCachedCenter(),this.zoom,{forceZoomChange:!0})},getTileSize:function(){return this.tileSize},getBy:function(a,b,c){var d="function"==
1839 typeof c.test;return OpenLayers.Array.filter(this[a],function(a){return a[b]==c||d&&c.test(a[b])})},getLayersBy:function(a,b){return this.getBy("layers",a,b)},getLayersByName:function(a){return this.getLayersBy("name",a)},getLayersByClass:function(a){return this.getLayersBy("CLASS_NAME",a)},getControlsBy:function(a,b){return this.getBy("controls",a,b)},getControlsByClass:function(a){return this.getControlsBy("CLASS_NAME",a)},getLayer:function(a){for(var b=null,c=0,d=this.layers.length;c<d;c++){var e=
1840 this.layers[c];if(e.id==a){b=e;break}}return b},setLayerZIndex:function(a,b){a.setZIndex(this.Z_INDEX_BASE[a.isBaseLayer?"BaseLayer":"Overlay"]+5*b)},resetLayersZIndex:function(){for(var a=0,b=this.layers.length;a<b;a++)this.setLayerZIndex(this.layers[a],a)},addLayer:function(a){for(var b=0,c=this.layers.length;b<c;b++)if(this.layers[b]==a)return!1;if(!1===this.events.triggerEvent("preaddlayer",{layer:a}))return!1;this.allOverlays&&(a.isBaseLayer=!1);a.div.className="olLayerDiv";a.div.style.overflow=
1841 "";this.setLayerZIndex(a,this.layers.length);a.isFixed?this.viewPortDiv.appendChild(a.div):this.layerContainerDiv.appendChild(a.div);this.layers.push(a);a.setMap(this);a.isBaseLayer||this.allOverlays&&!this.baseLayer?null==this.baseLayer?this.setBaseLayer(a):a.setVisibility(!1):a.redraw();this.events.triggerEvent("addlayer",{layer:a});a.events.triggerEvent("added",{map:this,layer:a});a.afterAdd();return!0},addLayers:function(a){for(var b=0,c=a.length;b<c;b++)this.addLayer(a[b])},removeLayer:function(a,
1842 b){if(!1!==this.events.triggerEvent("preremovelayer",{layer:a})){null==b&&(b=!0);a.isFixed?this.viewPortDiv.removeChild(a.div):this.layerContainerDiv.removeChild(a.div);OpenLayers.Util.removeItem(this.layers,a);a.removeMap(this);a.map=null;if(this.baseLayer==a&&(this.baseLayer=null,b))for(var c=0,d=this.layers.length;c<d;c++){var e=this.layers[c];if(e.isBaseLayer||this.allOverlays){this.setBaseLayer(e);break}}this.resetLayersZIndex();this.events.triggerEvent("removelayer",{layer:a});a.events.triggerEvent("removed",
1843 {map:this,layer:a})}},getNumLayers:function(){return this.layers.length},getLayerIndex:function(a){return OpenLayers.Util.indexOf(this.layers,a)},setLayerIndex:function(a,b){var c=this.getLayerIndex(a);0>b?b=0:b>this.layers.length&&(b=this.layers.length);if(c!=b){this.layers.splice(c,1);this.layers.splice(b,0,a);for(var c=0,d=this.layers.length;c<d;c++)this.setLayerZIndex(this.layers[c],c);this.events.triggerEvent("changelayer",{layer:a,property:"order"});this.allOverlays&&(0===b?this.setBaseLayer(a):
1844 this.baseLayer!==this.layers[0]&&this.setBaseLayer(this.layers[0]))}},raiseLayer:function(a,b){var c=this.getLayerIndex(a)+b;this.setLayerIndex(a,c)},setBaseLayer:function(a){if(a!=this.baseLayer&&-1!=OpenLayers.Util.indexOf(this.layers,a)){var b=this.getCachedCenter(),c=OpenLayers.Util.getResolutionFromScale(this.getScale(),a.units);null==this.baseLayer||this.allOverlays||this.baseLayer.setVisibility(!1);this.baseLayer=a;if(!this.allOverlays||this.baseLayer.visibility)this.baseLayer.setVisibility(!0),
1845 !1===this.baseLayer.inRange&&this.baseLayer.redraw();null!=b&&(a=this.getZoomForResolution(c||this.resolution,!0),this.setCenter(b,a,!1,!0));this.events.triggerEvent("changebaselayer",{layer:this.baseLayer})}},addControl:function(a,b){this.controls.push(a);this.addControlToMap(a,b)},addControls:function(a,b){for(var c=1===arguments.length?[]:b,d=0,e=a.length;d<e;d++)this.addControl(a[d],c[d]?c[d]:null)},addControlToMap:function(a,b){a.outsideViewport=null!=a.div;this.displayProjection&&!a.displayProjection&&
1846 (a.displayProjection=this.displayProjection);a.setMap(this);var c=a.draw(b);c&&!a.outsideViewport&&(c.style.zIndex=this.Z_INDEX_BASE.Control+this.controls.length,this.viewPortDiv.appendChild(c));a.autoActivate&&a.activate()},getControl:function(a){for(var b=null,c=0,d=this.controls.length;c<d;c++){var e=this.controls[c];if(e.id==a){b=e;break}}return b},removeControl:function(a){a&&a==this.getControl(a.id)&&(a.div&&a.div.parentNode==this.viewPortDiv&&this.viewPortDiv.removeChild(a.div),OpenLayers.Util.removeItem(this.controls,
1847 a))},addPopup:function(a,b){if(b)for(var c=this.popups.length-1;0<=c;--c)this.removePopup(this.popups[c]);a.map=this;this.popups.push(a);if(c=a.draw())c.style.zIndex=this.Z_INDEX_BASE.Popup+this.popups.length,this.layerContainerDiv.appendChild(c)},removePopup:function(a){OpenLayers.Util.removeItem(this.popups,a);if(a.div)try{this.layerContainerDiv.removeChild(a.div)}catch(b){}a.map=null},getSize:function(){var a=null;null!=this.size&&(a=this.size.clone());return a},updateSize:function(){var a=this.getCurrentSize();
1848 if(a&&!isNaN(a.h)&&!isNaN(a.w)){this.events.clearMouseCache();var b=this.getSize();null==b&&(this.size=b=a);if(!a.equals(b)){this.size=a;a=0;for(b=this.layers.length;a<b;a++)this.layers[a].onMapResize();a=this.getCachedCenter();null!=this.baseLayer&&null!=a&&(b=this.getZoom(),this.zoom=null,this.setCenter(a,b))}}this.events.triggerEvent("updatesize")},getCurrentSize:function(){var a=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(0==a.w&&0==a.h||isNaN(a.w)&&isNaN(a.h))a.w=this.div.offsetWidth,
1849 a.h=this.div.offsetHeight;if(0==a.w&&0==a.h||isNaN(a.w)&&isNaN(a.h))a.w=parseInt(this.div.style.width),a.h=parseInt(this.div.style.height);return a},calculateBounds:function(a,b){var c=null;null==a&&(a=this.getCachedCenter());null==b&&(b=this.getResolution());if(null!=a&&null!=b)var c=this.size.w*b/2,d=this.size.h*b/2,c=new OpenLayers.Bounds(a.lon-c,a.lat-d,a.lon+c,a.lat+d);return c},getCenter:function(){var a=null,b=this.getCachedCenter();b&&(a=b.clone());return a},getCachedCenter:function(){!this.center&&
1850 this.size&&(this.center=this.getLonLatFromViewPortPx({x:this.size.w/2,y:this.size.h/2}));return this.center},getZoom:function(){return this.zoom},pan:function(a,b,c){c=OpenLayers.Util.applyDefaults(c,{animate:!0,dragging:!1});if(c.dragging)0==a&&0==b||this.moveByPx(a,b);else{var d=this.getViewPortPxFromLonLat(this.getCachedCenter());a=d.add(a,b);if(this.dragging||!a.equals(d))d=this.getLonLatFromViewPortPx(a),c.animate?this.panTo(d):(this.moveTo(d),this.dragging&&(this.dragging=!1,this.events.triggerEvent("moveend")))}},
1851 panTo:function(a){if(this.panTween&&this.getExtent().scale(this.panRatio).containsLonLat(a)){var b=this.getCachedCenter();if(!a.equals(b)){var b=this.getPixelFromLonLat(b),c=this.getPixelFromLonLat(a),d=0,e=0;this.panTween.start({x:0,y:0},{x:c.x-b.x,y:c.y-b.y},this.panDuration,{callbacks:{eachStep:OpenLayers.Function.bind(function(a){this.moveByPx(a.x-d,a.y-e);d=Math.round(a.x);e=Math.round(a.y)},this),done:OpenLayers.Function.bind(function(b){this.moveTo(a);this.dragging=!1;this.events.triggerEvent("moveend")},
1852 this)}})}}else this.setCenter(a)},setCenter:function(a,b,c,d){this.panTween&&this.panTween.stop();this.zoomTween&&this.zoomTween.stop();this.moveTo(a,b,{dragging:c,forceZoomChange:d})},moveByPx:function(a,b){var c=this.size.w/2,d=this.size.h/2,e=c+a,f=d+b,g=this.baseLayer.wrapDateLine,h=0,k=0;this.restrictedExtent&&(h=c,k=d,g=!1);a=g||e<=this.maxPx.x-h&&e>=this.minPx.x+h?Math.round(a):0;b=f<=this.maxPx.y-k&&f>=this.minPx.y+k?Math.round(b):0;if(a||b){this.dragging||(this.dragging=!0,this.events.triggerEvent("movestart"));
1853 this.center=null;a&&(this.layerContainerOriginPx.x-=a,this.minPx.x-=a,this.maxPx.x-=a);b&&(this.layerContainerOriginPx.y-=b,this.minPx.y-=b,this.maxPx.y-=b);this.applyTransform();d=0;for(e=this.layers.length;d<e;++d)c=this.layers[d],c.visibility&&(c===this.baseLayer||c.inRange)&&(c.moveByPx(a,b),c.events.triggerEvent("move"));this.events.triggerEvent("move")}},adjustZoom:function(a){if(this.baseLayer&&this.baseLayer.wrapDateLine){var b=this.baseLayer.resolutions,c=this.getMaxExtent().getWidth()/this.size.w;
1854 if(this.getResolutionForZoom(a)>c)if(this.fractionalZoom)a=this.getZoomForResolution(c);else for(var d=a|0,e=b.length;d<e;++d)if(b[d]<=c){a=d;break}}return a},getMinZoom:function(){return this.adjustZoom(0)},moveTo:function(a,b,c){null==a||a instanceof OpenLayers.LonLat||(a=new OpenLayers.LonLat(a));c||(c={});null!=b&&(b=parseFloat(b),this.fractionalZoom||(b=Math.round(b)));var d=b;b=this.adjustZoom(b);b!==d&&(a=this.getCenter());var d=c.dragging||this.dragging,e=c.forceZoomChange;this.getCachedCenter()||
1855 this.isValidLonLat(a)||(a=this.maxExtent.getCenterLonLat(),this.center=a.clone());if(null!=this.restrictedExtent){null==a&&(a=this.center);null==b&&(b=this.getZoom());var f=this.getResolutionForZoom(b),f=this.calculateBounds(a,f);if(!this.restrictedExtent.containsBounds(f)){var g=this.restrictedExtent.getCenterLonLat();f.getWidth()>this.restrictedExtent.getWidth()?a=new OpenLayers.LonLat(g.lon,a.lat):f.left<this.restrictedExtent.left?a=a.add(this.restrictedExtent.left-f.left,0):f.right>this.restrictedExtent.right&&
1856 (a=a.add(this.restrictedExtent.right-f.right,0));f.getHeight()>this.restrictedExtent.getHeight()?a=new OpenLayers.LonLat(a.lon,g.lat):f.bottom<this.restrictedExtent.bottom?a=a.add(0,this.restrictedExtent.bottom-f.bottom):f.top>this.restrictedExtent.top&&(a=a.add(0,this.restrictedExtent.top-f.top))}}e=e||this.isValidZoomLevel(b)&&b!=this.getZoom();f=this.isValidLonLat(a)&&!a.equals(this.center);if(e||f||d){d||this.events.triggerEvent("movestart",{zoomChanged:e});f&&(!e&&this.center&&this.centerLayerContainer(a),
1857 this.center=a.clone());a=e?this.getResolutionForZoom(b):this.getResolution();if(e||null==this.layerContainerOrigin){this.layerContainerOrigin=this.getCachedCenter();this.layerContainerOriginPx.x=0;this.layerContainerOriginPx.y=0;this.applyTransform();var f=this.getMaxExtent({restricted:!0}),h=f.getCenterLonLat(),g=this.center.lon-h.lon,h=h.lat-this.center.lat,k=Math.round(f.getWidth()/a),l=Math.round(f.getHeight()/a);this.minPx={x:(this.size.w-k)/2-g/a,y:(this.size.h-l)/2-h/a};this.maxPx={x:this.minPx.x+
1858 Math.round(f.getWidth()/a),y:this.minPx.y+Math.round(f.getHeight()/a)}}e&&(this.zoom=b,this.resolution=a);a=this.getExtent();this.baseLayer.visibility&&(this.baseLayer.moveTo(a,e,c.dragging),c.dragging||this.baseLayer.events.triggerEvent("moveend",{zoomChanged:e}));a=this.baseLayer.getExtent();for(b=this.layers.length-1;0<=b;--b)f=this.layers[b],f===this.baseLayer||f.isBaseLayer||(g=f.calculateInRange(),f.inRange!=g&&((f.inRange=g)||f.display(!1),this.events.triggerEvent("changelayer",{layer:f,property:"visibility"})),
1859 g&&f.visibility&&(f.moveTo(a,e,c.dragging),c.dragging||f.events.triggerEvent("moveend",{zoomChanged:e})));this.events.triggerEvent("move");d||this.events.triggerEvent("moveend");if(e){b=0;for(c=this.popups.length;b<c;b++)this.popups[b].updatePosition();this.events.triggerEvent("zoomend")}}},centerLayerContainer:function(a){var b=this.getViewPortPxFromLonLat(this.layerContainerOrigin),c=this.getViewPortPxFromLonLat(a);if(null!=b&&null!=c){var d=this.layerContainerOriginPx.x;a=this.layerContainerOriginPx.y;
1860 var e=Math.round(b.x-c.x),b=Math.round(b.y-c.y);this.applyTransform(this.layerContainerOriginPx.x=e,this.layerContainerOriginPx.y=b);d-=e;a-=b;this.minPx.x-=d;this.maxPx.x-=d;this.minPx.y-=a;this.maxPx.y-=a}},isValidZoomLevel:function(a){return null!=a&&0<=a&&a<this.getNumZoomLevels()},isValidLonLat:function(a){var b=!1;null!=a&&(b=this.getMaxExtent(),b=b.containsLonLat(a,{worldBounds:this.baseLayer.wrapDateLine&&b}));return b},getProjection:function(){var a=this.getProjectionObject();return a?a.getCode():
1861 null},getProjectionObject:function(){var a=null;null!=this.baseLayer&&(a=this.baseLayer.projection);return a},getMaxResolution:function(){var a=null;null!=this.baseLayer&&(a=this.baseLayer.maxResolution);return a},getMaxExtent:function(a){var b=null;a&&a.restricted&&this.restrictedExtent?b=this.restrictedExtent:null!=this.baseLayer&&(b=this.baseLayer.maxExtent);return b},getNumZoomLevels:function(){var a=null;null!=this.baseLayer&&(a=this.baseLayer.numZoomLevels);return a},getExtent:function(){var a=
1862 null;null!=this.baseLayer&&(a=this.baseLayer.getExtent());return a},getResolution:function(){var a=null;null!=this.baseLayer?a=this.baseLayer.getResolution():!0===this.allOverlays&&0<this.layers.length&&(a=this.layers[0].getResolution());return a},getUnits:function(){var a=null;null!=this.baseLayer&&(a=this.baseLayer.units);return a},getScale:function(){var a=null;null!=this.baseLayer&&(a=this.getResolution(),a=OpenLayers.Util.getScaleFromResolution(a,this.baseLayer.units));return a},getZoomForExtent:function(a,
1863 b){var c=null;null!=this.baseLayer&&(c=this.baseLayer.getZoomForExtent(a,b));return c},getResolutionForZoom:function(a){var b=null;this.baseLayer&&(b=this.baseLayer.getResolutionForZoom(a));return b},getZoomForResolution:function(a,b){var c=null;null!=this.baseLayer&&(c=this.baseLayer.getZoomForResolution(a,b));return c},zoomTo:function(a,b){var c=this;if(c.isValidZoomLevel(a))if(c.baseLayer.wrapDateLine&&(a=c.adjustZoom(a)),c.zoomTween){var d=c.getResolution(),e=c.getResolutionForZoom(a),f={scale:1},
1864 d={scale:d/e};c.zoomTween.playing&&c.zoomTween.duration<3*c.zoomDuration?c.zoomTween.finish={scale:c.zoomTween.finish.scale*d.scale}:(b||(e=c.getSize(),b={x:e.w/2,y:e.h/2}),c.zoomTween.start(f,d,c.zoomDuration,{minFrameRate:50,callbacks:{eachStep:function(a){var d=c.layerContainerOriginPx;a=a.scale;c.applyTransform(d.x+((a-1)*(d.x-b.x)|0),d.y+((a-1)*(d.y-b.y)|0),a)},done:function(a){c.applyTransform();a=c.getResolution()/a.scale;var d=c.getZoomForResolution(a,!0);c.moveTo(c.getZoomTargetCenter(b,
1865 a),d,!0)}}}))}else f=b?c.getZoomTargetCenter(b,c.getResolutionForZoom(a)):null,c.setCenter(f,a)},zoomIn:function(){this.zoomTo(this.getZoom()+1)},zoomOut:function(){this.zoomTo(this.getZoom()-1)},zoomToExtent:function(a,b){a instanceof OpenLayers.Bounds||(a=new OpenLayers.Bounds(a));var c=a.getCenterLonLat();if(this.baseLayer.wrapDateLine){c=this.getMaxExtent();for(a=a.clone();a.right<a.left;)a.right+=c.getWidth();c=a.getCenterLonLat().wrapDateLine(c)}this.setCenter(c,this.getZoomForExtent(a,b))},
1866 zoomToMaxExtent:function(a){a=this.getMaxExtent({restricted:a?a.restricted:!0});this.zoomToExtent(a)},zoomToScale:function(a,b){var c=OpenLayers.Util.getResolutionFromScale(a,this.baseLayer.units),d=this.size.w*c/2,c=this.size.h*c/2,e=this.getCachedCenter(),d=new OpenLayers.Bounds(e.lon-d,e.lat-c,e.lon+d,e.lat+c);this.zoomToExtent(d,b)},getLonLatFromViewPortPx:function(a){var b=null;null!=this.baseLayer&&(b=this.baseLayer.getLonLatFromViewPortPx(a));return b},getViewPortPxFromLonLat:function(a){var b=
1867 null;null!=this.baseLayer&&(b=this.baseLayer.getViewPortPxFromLonLat(a));return b},getZoomTargetCenter:function(a,b){var c=null,d=this.getSize(),e=d.w/2-a.x,d=a.y-d.h/2,f=this.getLonLatFromPixel(a);f&&(c=new OpenLayers.LonLat(f.lon+e*b,f.lat+d*b));return c},getLonLatFromPixel:function(a){return this.getLonLatFromViewPortPx(a)},getPixelFromLonLat:function(a){a=this.getViewPortPxFromLonLat(a);a.x=Math.round(a.x);a.y=Math.round(a.y);return a},getGeodesicPixelSize:function(a){var b=a?this.getLonLatFromPixel(a):
1868 this.getCachedCenter()||new OpenLayers.LonLat(0,0),c=this.getResolution();a=b.add(-c/2,0);var d=b.add(c/2,0),e=b.add(0,-c/2),b=b.add(0,c/2),c=new OpenLayers.Projection("EPSG:4326"),f=this.getProjectionObject()||c;f.equals(c)||(a.transform(f,c),d.transform(f,c),e.transform(f,c),b.transform(f,c));return new OpenLayers.Size(OpenLayers.Util.distVincenty(a,d),OpenLayers.Util.distVincenty(e,b))},getViewPortPxFromLayerPx:function(a){var b=null;null!=a&&(b=a.add(this.layerContainerOriginPx.x,this.layerContainerOriginPx.y));
1869 return b},getLayerPxFromViewPortPx:function(a){var b=null;null!=a&&(b=a.add(-this.layerContainerOriginPx.x,-this.layerContainerOriginPx.y),isNaN(b.x)||isNaN(b.y))&&(b=null);return b},getLonLatFromLayerPx:function(a){a=this.getViewPortPxFromLayerPx(a);return this.getLonLatFromViewPortPx(a)},getLayerPxFromLonLat:function(a){a=this.getPixelFromLonLat(a);return this.getLayerPxFromViewPortPx(a)},applyTransform:function(a,b,c){c=c||1;var d=this.layerContainerOriginPx,e=1!==c;a=a||d.x;b=b||d.y;var f=this.layerContainerDiv.style,
1870 g=this.applyTransform.transform,h=this.applyTransform.template;if(void 0===g&&(g=OpenLayers.Util.vendorPrefix.style("transform"),this.applyTransform.transform=g)){var k=OpenLayers.Element.getStyle(this.viewPortDiv,OpenLayers.Util.vendorPrefix.css("transform"));k&&"none"===k||(h=["translate3d(",",0) ","scale3d(",",1)"],f[g]=[h[0],"0,0",h[1]].join(""));h&&~f[g].indexOf(h[0])||(h=["translate(",") ","scale(",")"]);this.applyTransform.template=h}null===g||"translate3d("!==h[0]&&!0!==e?(f.left=a+"px",f.top=
1871 b+"px",null!==g&&(f[g]="")):(!0===e&&"translate("===h[0]&&(a-=d.x,b-=d.y,f.left=d.x+"px",f.top=d.y+"px"),f[g]=[h[0],a,"px,",b,"px",h[1],h[2],c,",",c,h[3]].join(""))},CLASS_NAME:"OpenLayers.Map"});OpenLayers.Map.TILE_WIDTH=256;OpenLayers.Map.TILE_HEIGHT=256;OpenLayers.Handler=OpenLayers.Class({id:null,control:null,map:null,keyMask:null,active:!1,evt:null,touch:!1,initialize:function(a,b,c){OpenLayers.Util.extend(this,c);this.control=a;this.callbacks=b;(a=this.map||a.map)&&this.setMap(a);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},setMap:function(a){this.map=a},checkModifiers:function(a){return null==this.keyMask?!0:((a.shiftKey?OpenLayers.Handler.MOD_SHIFT:0)|(a.ctrlKey?OpenLayers.Handler.MOD_CTRL:0)|(a.altKey?OpenLayers.Handler.MOD_ALT:
1872 0)|(a.metaKey?OpenLayers.Handler.MOD_META:0))==this.keyMask},activate:function(){if(this.active)return!1;for(var a=OpenLayers.Events.prototype.BROWSER_EVENTS,b=0,c=a.length;b<c;b++)this[a[b]]&&this.register(a[b],this[a[b]]);return this.active=!0},deactivate:function(){if(!this.active)return!1;for(var a=OpenLayers.Events.prototype.BROWSER_EVENTS,b=0,c=a.length;b<c;b++)this[a[b]]&&this.unregister(a[b],this[a[b]]);this.active=this.touch=!1;return!0},startTouch:function(){if(!this.touch){this.touch=!0;
1873 for(var a="mousedown mouseup mousemove click dblclick mouseout".split(" "),b=0,c=a.length;b<c;b++)this[a[b]]&&this.unregister(a[b],this[a[b]])}},callback:function(a,b){a&&this.callbacks[a]&&this.callbacks[a].apply(this.control,b)},register:function(a,b){this.map.events.registerPriority(a,this,b);this.map.events.registerPriority(a,this,this.setEvent)},unregister:function(a,b){this.map.events.unregister(a,this,b);this.map.events.unregister(a,this,this.setEvent)},setEvent:function(a){this.evt=a;return!0},
1874 destroy:function(){this.deactivate();this.control=this.map=null},CLASS_NAME:"OpenLayers.Handler"});OpenLayers.Handler.MOD_NONE=0;OpenLayers.Handler.MOD_SHIFT=1;OpenLayers.Handler.MOD_CTRL=2;OpenLayers.Handler.MOD_ALT=4;OpenLayers.Handler.MOD_META=8;OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:!0,"double":!1,pixelTolerance:0,dblclickTolerance:13,stopSingle:!1,stopDouble:!1,timerId:null,down:null,last:null,first:null,rightclickTimerId:null,touchstart:function(a){this.startTouch();this.down=this.getEventInfo(a);this.last=this.getEventInfo(a);return!0},touchmove:function(a){this.last=this.getEventInfo(a);return!0},touchend:function(a){this.down&&(a.xy=this.last.xy,a.lastTouches=this.last.touches,this.handleSingle(a),
1875 this.down=null);return!0},mousedown:function(a){this.down=this.getEventInfo(a);this.last=this.getEventInfo(a);return!0},mouseup:function(a){var b=!0;this.checkModifiers(a)&&(this.control.handleRightClicks&&OpenLayers.Event.isRightClick(a))&&(b=this.rightclick(a));return b},rightclick:function(a){if(this.passesTolerance(a)){if(null!=this.rightclickTimerId)return this.clearTimer(),this.callback("dblrightclick",[a]),!this.stopDouble;a=this["double"]?OpenLayers.Util.extend({},a):this.callback("rightclick",
1876 [a]);a=OpenLayers.Function.bind(this.delayedRightCall,this,a);this.rightclickTimerId=window.setTimeout(a,this.delay)}return!this.stopSingle},delayedRightCall:function(a){this.rightclickTimerId=null;a&&this.callback("rightclick",[a])},click:function(a){this.last||(this.last=this.getEventInfo(a));this.handleSingle(a);return!this.stopSingle},dblclick:function(a){this.handleDouble(a);return!this.stopDouble},handleDouble:function(a){this.passesDblclickTolerance(a)&&(this["double"]&&this.callback("dblclick",
1877 [a]),this.clearTimer())},handleSingle:function(a){this.passesTolerance(a)&&(null!=this.timerId?(this.last.touches&&1===this.last.touches.length&&(this["double"]&&OpenLayers.Event.preventDefault(a),this.handleDouble(a)),this.last.touches&&2===this.last.touches.length||this.clearTimer()):(this.first=this.getEventInfo(a),a=this.single?OpenLayers.Util.extend({},a):null,this.queuePotentialClick(a)))},queuePotentialClick:function(a){this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,
1878 this,a),this.delay)},passesTolerance:function(a){var b=!0;if(null!=this.pixelTolerance&&this.down&&this.down.xy&&(b=this.pixelTolerance>=this.down.xy.distanceTo(a.xy))&&this.touch&&this.down.touches.length===this.last.touches.length){a=0;for(var c=this.down.touches.length;a<c;++a)if(this.getTouchDistance(this.down.touches[a],this.last.touches[a])>this.pixelTolerance){b=!1;break}}return b},getTouchDistance:function(a,b){return Math.sqrt(Math.pow(a.clientX-b.clientX,2)+Math.pow(a.clientY-b.clientY,
1879 2))},passesDblclickTolerance:function(a){a=!0;this.down&&this.first&&(a=this.down.xy.distanceTo(this.first.xy)<=this.dblclickTolerance);return a},clearTimer:function(){null!=this.timerId&&(window.clearTimeout(this.timerId),this.timerId=null);null!=this.rightclickTimerId&&(window.clearTimeout(this.rightclickTimerId),this.rightclickTimerId=null)},delayedCall:function(a){this.timerId=null;a&&this.callback("click",[a])},getEventInfo:function(a){var b;if(a.touches){var c=a.touches.length;b=Array(c);for(var d,
1880 e=0;e<c;e++)d=a.touches[e],b[e]={clientX:d.olClientX,clientY:d.olClientY}}return{xy:a.xy,touches:b}},deactivate:function(){var a=!1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.clearTimer(),this.last=this.first=this.down=null,a=!0);return a},CLASS_NAME:"OpenLayers.Handler.Click"});OpenLayers.Handler.Drag=OpenLayers.Class(OpenLayers.Handler,{started:!1,stopDown:!0,dragging:!1,last:null,start:null,lastMoveEvt:null,oldOnselectstart:null,interval:0,timeoutId:null,documentDrag:!1,documentEvents:null,initialize:function(a,b,c){OpenLayers.Handler.prototype.initialize.apply(this,arguments);if(!0===this.documentDrag){var d=this;this._docMove=function(a){d.mousemove({xy:{x:a.clientX,y:a.clientY},element:document})};this._docUp=function(a){d.mouseup({xy:{x:a.clientX,y:a.clientY}})}}},
1881 dragstart:function(a){var b=!0;this.dragging=!1;this.checkModifiers(a)&&(OpenLayers.Event.isLeftClick(a)||OpenLayers.Event.isSingleTouch(a))?(this.started=!0,this.last=this.start=a.xy,OpenLayers.Element.addClass(this.map.viewPortDiv,"olDragDown"),this.down(a),this.callback("down",[a.xy]),OpenLayers.Event.preventDefault(a),this.oldOnselectstart||(this.oldOnselectstart=document.onselectstart?document.onselectstart:OpenLayers.Function.True),document.onselectstart=OpenLayers.Function.False,b=!this.stopDown):
1882 (this.started=!1,this.last=this.start=null);return b},dragmove:function(a){this.lastMoveEvt=a;!this.started||(this.timeoutId||a.xy.x==this.last.x&&a.xy.y==this.last.y)||(!0===this.documentDrag&&this.documentEvents&&(a.element===document?(this.adjustXY(a),this.setEvent(a)):this.removeDocumentEvents()),0<this.interval&&(this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval)),this.dragging=!0,this.move(a),this.callback("move",[a.xy]),this.oldOnselectstart||(this.oldOnselectstart=
1883 document.onselectstart,document.onselectstart=OpenLayers.Function.False),this.last=a.xy);return!0},dragend:function(a){if(this.started){!0===this.documentDrag&&this.documentEvents&&(this.adjustXY(a),this.removeDocumentEvents());var b=this.start!=this.last;this.dragging=this.started=!1;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(a);this.callback("up",[a.xy]);b&&this.callback("done",[a.xy]);document.onselectstart=this.oldOnselectstart}return!0},down:function(a){},move:function(a){},
1884 up:function(a){},out:function(a){},mousedown:function(a){return this.dragstart(a)},touchstart:function(a){this.startTouch();return this.dragstart(a)},mousemove:function(a){return this.dragmove(a)},touchmove:function(a){return this.dragmove(a)},removeTimeout:function(){this.timeoutId=null;this.dragging&&this.mousemove(this.lastMoveEvt)},mouseup:function(a){return this.dragend(a)},touchend:function(a){a.xy=this.last;return this.dragend(a)},mouseout:function(a){if(this.started&&OpenLayers.Util.mouseLeft(a,
1885 this.map.viewPortDiv))if(!0===this.documentDrag)this.addDocumentEvents();else{var b=this.start!=this.last;this.dragging=this.started=!1;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(a);this.callback("out",[]);b&&this.callback("done",[a.xy]);document.onselectstart&&(document.onselectstart=this.oldOnselectstart)}return!0},click:function(a){return this.start==this.last},activate:function(){var a=!1;OpenLayers.Handler.prototype.activate.apply(this,arguments)&&(this.dragging=
1886 !1,a=!0);return a},deactivate:function(){var a=!1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.dragging=this.started=!1,this.last=this.start=null,a=!0,OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown"));return a},adjustXY:function(a){var b=OpenLayers.Util.pagePosition(this.map.viewPortDiv);a.xy.x-=b[0];a.xy.y-=b[1]},addDocumentEvents:function(){OpenLayers.Element.addClass(document.body,"olDragDown");this.documentEvents=!0;OpenLayers.Event.observe(document,"mousemove",
1887 this._docMove);OpenLayers.Event.observe(document,"mouseup",this._docUp)},removeDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents=!1;OpenLayers.Event.stopObserving(document,"mousemove",this._docMove);OpenLayers.Event.stopObserving(document,"mouseup",this._docUp)},CLASS_NAME:"OpenLayers.Handler.Drag"});OpenLayers.Control.OverviewMap=OpenLayers.Class(OpenLayers.Control,{element:null,ovmap:null,size:{w:180,h:90},layers:null,minRectSize:15,minRectDisplayClass:"RectReplacement",minRatio:8,maxRatio:32,mapOptions:null,autoPan:!1,handlers:null,resolutionFactor:1,maximized:!1,maximizeTitle:"",minimizeTitle:"",initialize:function(a){this.layers=[];this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,[a])},destroy:function(){this.mapDiv&&(this.handlers.click&&this.handlers.click.destroy(),
1888 this.handlers.drag&&this.handlers.drag.destroy(),this.ovmap&&this.ovmap.viewPortDiv.removeChild(this.extentRectangle),this.extentRectangle=null,this.rectEvents&&(this.rectEvents.destroy(),this.rectEvents=null),this.ovmap&&(this.ovmap.destroy(),this.ovmap=null),this.element.removeChild(this.mapDiv),this.mapDiv=null,this.div.removeChild(this.element),this.element=null,this.maximizeDiv&&(this.div.removeChild(this.maximizeDiv),this.maximizeDiv=null),this.minimizeDiv&&(this.div.removeChild(this.minimizeDiv),
1889 this.minimizeDiv=null),this.map.events.un({buttonclick:this.onButtonClick,moveend:this.update,changebaselayer:this.baseLayerDraw,scope:this}),OpenLayers.Control.prototype.destroy.apply(this,arguments))},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(0===this.layers.length)if(this.map.baseLayer)this.layers=[this.map.baseLayer.clone()];else return this.map.events.register("changebaselayer",this,this.baseLayerDraw),this.div;this.element=document.createElement("div");this.element.className=
1890 this.displayClass+"Element";this.element.style.display="none";this.mapDiv=document.createElement("div");this.mapDiv.style.width=this.size.w+"px";this.mapDiv.style.height=this.size.h+"px";this.mapDiv.style.position="relative";this.mapDiv.style.overflow="hidden";this.mapDiv.id=OpenLayers.Util.createUniqueID("overviewMap");this.extentRectangle=document.createElement("div");this.extentRectangle.style.position="absolute";this.extentRectangle.style.zIndex=1E3;this.extentRectangle.className=this.displayClass+
1891 "ExtentRectangle";this.element.appendChild(this.mapDiv);this.div.appendChild(this.element);if(this.outsideViewport)this.element.style.display="";else{this.div.className+=" "+this.displayClass+"Container";var a=OpenLayers.Util.getImageLocation("layer-switcher-maximize.png");this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv(this.displayClass+"MaximizeButton",null,null,a,"absolute");this.maximizeDiv.style.display="none";this.maximizeDiv.className=this.displayClass+"MaximizeButton olButton";this.maximizeTitle&&
1892 (this.maximizeDiv.title=this.maximizeTitle);this.div.appendChild(this.maximizeDiv);a=OpenLayers.Util.getImageLocation("layer-switcher-minimize.png");this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_minimizeDiv",null,null,a,"absolute");this.minimizeDiv.style.display="none";this.minimizeDiv.className=this.displayClass+"MinimizeButton olButton";this.minimizeTitle&&(this.minimizeDiv.title=this.minimizeTitle);this.div.appendChild(this.minimizeDiv);this.minimizeControl()}this.map.getExtent()&&
1893 this.update();this.map.events.on({buttonclick:this.onButtonClick,moveend:this.update,scope:this});this.maximized&&this.maximizeControl();return this.div},baseLayerDraw:function(){this.draw();this.map.events.unregister("changebaselayer",this,this.baseLayerDraw)},rectDrag:function(a){var b=this.handlers.drag.last.x-a.x,c=this.handlers.drag.last.y-a.y;if(0!=b||0!=c){var d=this.rectPxBounds.top,e=this.rectPxBounds.left;a=Math.abs(this.rectPxBounds.getHeight());var f=this.rectPxBounds.getWidth(),c=Math.max(0,
1894 d-c),c=Math.min(c,this.ovmap.size.h-this.hComp-a),b=Math.max(0,e-b),b=Math.min(b,this.ovmap.size.w-this.wComp-f);this.setRectPxBounds(new OpenLayers.Bounds(b,c+a,b+f,c))}},mapDivClick:function(a){var b=this.rectPxBounds.getCenterPixel(),c=a.xy.x-b.x,d=a.xy.y-b.y,e=this.rectPxBounds.top,f=this.rectPxBounds.left;a=Math.abs(this.rectPxBounds.getHeight());b=this.rectPxBounds.getWidth();d=Math.max(0,e+d);d=Math.min(d,this.ovmap.size.h-a);c=Math.max(0,f+c);c=Math.min(c,this.ovmap.size.w-b);this.setRectPxBounds(new OpenLayers.Bounds(c,
1895 d+a,c+b,d));this.updateMapToRect()},onButtonClick:function(a){a.buttonElement===this.minimizeDiv?this.minimizeControl():a.buttonElement===this.maximizeDiv&&this.maximizeControl()},maximizeControl:function(a){this.element.style.display="";this.showToggle(!1);null!=a&&OpenLayers.Event.stop(a)},minimizeControl:function(a){this.element.style.display="none";this.showToggle(!0);null!=a&&OpenLayers.Event.stop(a)},showToggle:function(a){this.maximizeDiv&&(this.maximizeDiv.style.display=a?"":"none");this.minimizeDiv&&
1896 (this.minimizeDiv.style.display=a?"none":"")},update:function(){null==this.ovmap&&this.createMap();!this.autoPan&&this.isSuitableOverview()||this.updateOverview();this.updateRectToMap()},isSuitableOverview:function(){var a=this.map.getExtent(),b=this.map.getMaxExtent(),a=new OpenLayers.Bounds(Math.max(a.left,b.left),Math.max(a.bottom,b.bottom),Math.min(a.right,b.right),Math.min(a.top,b.top));this.ovmap.getProjection()!=this.map.getProjection()&&(a=a.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject()));
1897 b=this.ovmap.getResolution()/this.map.getResolution();return b>this.minRatio&&b<=this.maxRatio&&this.ovmap.getExtent().containsBounds(a)},updateOverview:function(){var a=this.map.getResolution(),b=this.ovmap.getResolution(),c=b/a;c>this.maxRatio?b=this.minRatio*a:c<=this.minRatio&&(b=this.maxRatio*a);this.ovmap.getProjection()!=this.map.getProjection()?(a=this.map.center.clone(),a.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject())):a=this.map.center;this.ovmap.setCenter(a,
1898 this.ovmap.getZoomForResolution(b*this.resolutionFactor));this.updateRectToMap()},createMap:function(){var a=OpenLayers.Util.extend({controls:[],maxResolution:"auto",fallThrough:!1},this.mapOptions);this.ovmap=new OpenLayers.Map(this.mapDiv,a);this.ovmap.viewPortDiv.appendChild(this.extentRectangle);OpenLayers.Event.stopObserving(window,"unload",this.ovmap.unloadDestroy);this.ovmap.addLayers(this.layers);this.ovmap.zoomToMaxExtent();this.wComp=(this.wComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,
1899 "border-left-width"))+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-right-width")))?this.wComp:2;this.hComp=(this.hComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-top-width"))+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-bottom-width")))?this.hComp:2;this.handlers.drag=new OpenLayers.Handler.Drag(this,{move:this.rectDrag,done:this.updateMapToRect},{map:this.ovmap});this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.mapDivClick},
1900 {single:!0,"double":!1,stopSingle:!0,stopDouble:!0,pixelTolerance:1,map:this.ovmap});this.handlers.click.activate();this.rectEvents=new OpenLayers.Events(this,this.extentRectangle,null,!0);this.rectEvents.register("mouseover",this,function(a){this.handlers.drag.active||this.map.dragging||this.handlers.drag.activate()});this.rectEvents.register("mouseout",this,function(a){this.handlers.drag.dragging||this.handlers.drag.deactivate()});if(this.ovmap.getProjection()!=this.map.getProjection()){var a=this.map.getProjectionObject().getUnits()||
1901 this.map.units||this.map.baseLayer.units,b=this.ovmap.getProjectionObject().getUnits()||this.ovmap.units||this.ovmap.baseLayer.units;this.resolutionFactor=a&&b?OpenLayers.INCHES_PER_UNIT[a]/OpenLayers.INCHES_PER_UNIT[b]:1}},updateRectToMap:function(){var a;a=this.ovmap.getProjection()!=this.map.getProjection()?this.map.getExtent().transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject()):this.map.getExtent();(a=this.getRectBoundsFromMapBounds(a))&&this.setRectPxBounds(a)},updateMapToRect:function(){var a=
1902 this.getMapBoundsFromRectBounds(this.rectPxBounds);this.ovmap.getProjection()!=this.map.getProjection()&&(a=a.transform(this.ovmap.getProjectionObject(),this.map.getProjectionObject()));this.map.panTo(a.getCenterLonLat())},setRectPxBounds:function(a){var b=Math.max(a.top,0),c=Math.max(a.left,0),d=Math.min(a.top+Math.abs(a.getHeight()),this.ovmap.size.h-this.hComp);a=Math.min(a.left+a.getWidth(),this.ovmap.size.w-this.wComp);var e=Math.max(a-c,0),f=Math.max(d-b,0);e<this.minRectSize||f<this.minRectSize?
1903 (this.extentRectangle.className=this.displayClass+this.minRectDisplayClass,e=c+e/2-this.minRectSize/2,this.extentRectangle.style.top=Math.round(b+f/2-this.minRectSize/2)+"px",this.extentRectangle.style.left=Math.round(e)+"px",this.extentRectangle.style.height=this.minRectSize+"px",this.extentRectangle.style.width=this.minRectSize+"px"):(this.extentRectangle.className=this.displayClass+"ExtentRectangle",this.extentRectangle.style.top=Math.round(b)+"px",this.extentRectangle.style.left=Math.round(c)+
1904 "px",this.extentRectangle.style.height=Math.round(f)+"px",this.extentRectangle.style.width=Math.round(e)+"px");this.rectPxBounds=new OpenLayers.Bounds(Math.round(c),Math.round(d),Math.round(a),Math.round(b))},getRectBoundsFromMapBounds:function(a){var b=this.getOverviewPxFromLonLat({lon:a.left,lat:a.bottom});a=this.getOverviewPxFromLonLat({lon:a.right,lat:a.top});var c=null;b&&a&&(c=new OpenLayers.Bounds(b.x,b.y,a.x,a.y));return c},getMapBoundsFromRectBounds:function(a){var b=this.getLonLatFromOverviewPx({x:a.left,
1905 y:a.bottom});a=this.getLonLatFromOverviewPx({x:a.right,y:a.top});return new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat)},getLonLatFromOverviewPx:function(a){var b=this.ovmap.size,c=this.ovmap.getResolution(),d=this.ovmap.getExtent().getCenterLonLat();return{lon:d.lon+(a.x-b.w/2)*c,lat:d.lat-(a.y-b.h/2)*c}},getOverviewPxFromLonLat:function(a){var b=this.ovmap.getResolution(),c=this.ovmap.getExtent();if(c)return{x:Math.round(1/b*(a.lon-c.left)),y:Math.round(1/b*(c.top-a.lat))}},CLASS_NAME:"OpenLayers.Control.OverviewMap"});OpenLayers.Layer=OpenLayers.Class({id:null,name:null,div:null,opacity:1,alwaysInRange:null,RESOLUTION_PROPERTIES:"scales resolutions maxScale minScale maxResolution minResolution numZoomLevels maxZoomLevel".split(" "),events:null,map:null,isBaseLayer:!1,alpha:!1,displayInLayerSwitcher:!0,visibility:!0,attribution:null,inRange:!1,imageSize:null,options:null,eventListeners:null,gutter:0,projection:null,units:null,scales:null,resolutions:null,maxExtent:null,minExtent:null,maxResolution:null,minResolution:null,
1906 numZoomLevels:null,minScale:null,maxScale:null,displayOutsideMaxExtent:!1,wrapDateLine:!1,metadata:null,initialize:function(a,b){this.metadata={};b=OpenLayers.Util.extend({},b);null!=this.alwaysInRange&&(b.alwaysInRange=this.alwaysInRange);this.addOptions(b);this.name=a;if(null==this.id&&(this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_"),this.div=OpenLayers.Util.createDiv(this.id),this.div.style.width="100%",this.div.style.height="100%",this.div.dir="ltr",this.events=new OpenLayers.Events(this,
1907 this.div),this.eventListeners instanceof Object))this.events.on(this.eventListeners)},destroy:function(a){null==a&&(a=!0);null!=this.map&&this.map.removeLayer(this,a);this.options=this.div=this.name=this.map=this.projection=null;this.events&&(this.eventListeners&&this.events.un(this.eventListeners),this.events.destroy());this.events=this.eventListeners=null},clone:function(a){null==a&&(a=new OpenLayers.Layer(this.name,this.getOptions()));OpenLayers.Util.applyDefaults(a,this);a.map=null;return a},
1908 getOptions:function(){var a={},b;for(b in this.options)a[b]=this[b];return a},setName:function(a){a!=this.name&&(this.name=a,null!=this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"name"}))},addOptions:function(a,b){null==this.options&&(this.options={});a&&("string"==typeof a.projection&&(a.projection=new OpenLayers.Projection(a.projection)),a.projection&&OpenLayers.Util.applyDefaults(a,OpenLayers.Projection.defaults[a.projection.getCode()]),!a.maxExtent||a.maxExtent instanceof
1909 OpenLayers.Bounds||(a.maxExtent=new OpenLayers.Bounds(a.maxExtent)),!a.minExtent||a.minExtent instanceof OpenLayers.Bounds||(a.minExtent=new OpenLayers.Bounds(a.minExtent)));OpenLayers.Util.extend(this.options,a);OpenLayers.Util.extend(this,a);this.projection&&this.projection.getUnits()&&(this.units=this.projection.getUnits());if(this.map){var c=this.map.getResolution(),d=this.RESOLUTION_PROPERTIES.concat(["projection","units","minExtent","maxExtent"]),e;for(e in a)if(a.hasOwnProperty(e)&&0<=OpenLayers.Util.indexOf(d,
1910 e)){this.initResolutions();b&&this.map.baseLayer===this&&(this.map.setCenter(this.map.getCenter(),this.map.getZoomForResolution(c),!1,!0),this.map.events.triggerEvent("changebaselayer",{layer:this}));break}}},onMapResize:function(){},redraw:function(){var a=!1;if(this.map){this.inRange=this.calculateInRange();var b=this.getExtent();b&&(this.inRange&&this.visibility)&&(this.moveTo(b,!0,!1),this.events.triggerEvent("moveend",{zoomChanged:!0}),a=!0)}return a},moveTo:function(a,b,c){a=this.visibility;
1911 this.isBaseLayer||(a=a&&this.inRange);this.display(a)},moveByPx:function(a,b){},setMap:function(a){null==this.map&&(this.map=a,this.maxExtent=this.maxExtent||this.map.maxExtent,this.minExtent=this.minExtent||this.map.minExtent,this.projection=this.projection||this.map.projection,"string"==typeof this.projection&&(this.projection=new OpenLayers.Projection(this.projection)),this.units=this.projection.getUnits()||this.units||this.map.units,this.initResolutions(),this.isBaseLayer||(this.inRange=this.calculateInRange(),
1912 this.div.style.display=this.visibility&&this.inRange?"":"none"),this.setTileSize())},afterAdd:function(){},removeMap:function(a){},getImageSize:function(a){return this.imageSize||this.tileSize},setTileSize:function(a){this.tileSize=a=a?a:this.tileSize?this.tileSize:this.map.getTileSize();this.gutter&&(this.imageSize=new OpenLayers.Size(a.w+2*this.gutter,a.h+2*this.gutter))},getVisibility:function(){return this.visibility},setVisibility:function(a){a!=this.visibility&&(this.visibility=a,this.display(a),
1913 this.redraw(),null!=this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"}),this.events.triggerEvent("visibilitychanged"))},display:function(a){a!=("none"!=this.div.style.display)&&(this.div.style.display=a&&this.calculateInRange()?"block":"none")},calculateInRange:function(){var a=!1;this.alwaysInRange?a=!0:this.map&&(a=this.map.getResolution(),a=a>=this.minResolution&&a<=this.maxResolution);return a},setIsBaseLayer:function(a){a!=this.isBaseLayer&&(this.isBaseLayer=
1914 a,null!=this.map&&this.map.events.triggerEvent("changebaselayer",{layer:this}))},initResolutions:function(){var a,b,c,d={},e=!0;a=0;for(b=this.RESOLUTION_PROPERTIES.length;a<b;a++)c=this.RESOLUTION_PROPERTIES[a],d[c]=this.options[c],e&&this.options[c]&&(e=!1);null==this.options.alwaysInRange&&(this.alwaysInRange=e);null==d.resolutions&&(d.resolutions=this.resolutionsFromScales(d.scales));null==d.resolutions&&(d.resolutions=this.calculateResolutions(d));if(null==d.resolutions){a=0;for(b=this.RESOLUTION_PROPERTIES.length;a<
1915 b;a++)c=this.RESOLUTION_PROPERTIES[a],d[c]=null!=this.options[c]?this.options[c]:this.map[c];null==d.resolutions&&(d.resolutions=this.resolutionsFromScales(d.scales));null==d.resolutions&&(d.resolutions=this.calculateResolutions(d))}var f;this.options.maxResolution&&"auto"!==this.options.maxResolution&&(f=this.options.maxResolution);this.options.minScale&&(f=OpenLayers.Util.getResolutionFromScale(this.options.minScale,this.units));var g;this.options.minResolution&&"auto"!==this.options.minResolution&&
1916 (g=this.options.minResolution);this.options.maxScale&&(g=OpenLayers.Util.getResolutionFromScale(this.options.maxScale,this.units));d.resolutions&&(d.resolutions.sort(function(a,b){return b-a}),f||(f=d.resolutions[0]),g||(g=d.resolutions[d.resolutions.length-1]));if(this.resolutions=d.resolutions){b=this.resolutions.length;this.scales=Array(b);for(a=0;a<b;a++)this.scales[a]=OpenLayers.Util.getScaleFromResolution(this.resolutions[a],this.units);this.numZoomLevels=b}if(this.minResolution=g)this.maxScale=
1917 OpenLayers.Util.getScaleFromResolution(g,this.units);if(this.maxResolution=f)this.minScale=OpenLayers.Util.getScaleFromResolution(f,this.units)},resolutionsFromScales:function(a){if(null!=a){var b,c,d;d=a.length;b=Array(d);for(c=0;c<d;c++)b[c]=OpenLayers.Util.getResolutionFromScale(a[c],this.units);return b}},calculateResolutions:function(a){var b,c,d=a.maxResolution;null!=a.minScale?d=OpenLayers.Util.getResolutionFromScale(a.minScale,this.units):"auto"==d&&null!=this.maxExtent&&(b=this.map.getSize(),
1918 c=this.maxExtent.getWidth()/b.w,b=this.maxExtent.getHeight()/b.h,d=Math.max(c,b));c=a.minResolution;null!=a.maxScale?c=OpenLayers.Util.getResolutionFromScale(a.maxScale,this.units):"auto"==a.minResolution&&null!=this.minExtent&&(b=this.map.getSize(),c=this.minExtent.getWidth()/b.w,b=this.minExtent.getHeight()/b.h,c=Math.max(c,b));"number"!==typeof d&&("number"!==typeof c&&null!=this.maxExtent)&&(d=this.map.getTileSize(),d=Math.max(this.maxExtent.getWidth()/d.w,this.maxExtent.getHeight()/d.h));b=a.maxZoomLevel;
1919 a=a.numZoomLevels;"number"===typeof c&&"number"===typeof d&&void 0===a?a=Math.floor(Math.log(d/c)/Math.log(2))+1:void 0===a&&null!=b&&(a=b+1);if(!("number"!==typeof a||0>=a||"number"!==typeof d&&"number"!==typeof c)){b=Array(a);var e=2;"number"==typeof c&&"number"==typeof d&&(e=Math.pow(d/c,1/(a-1)));var f;if("number"===typeof d)for(f=0;f<a;f++)b[f]=d/Math.pow(e,f);else for(f=0;f<a;f++)b[a-1-f]=c*Math.pow(e,f);return b}},getResolution:function(){var a=this.map.getZoom();return this.getResolutionForZoom(a)},
1920 getExtent:function(){return this.map.calculateBounds()},getZoomForExtent:function(a,b){var c=this.map.getSize(),c=Math.max(a.getWidth()/c.w,a.getHeight()/c.h);return this.getZoomForResolution(c,b)},getDataExtent:function(){},getResolutionForZoom:function(a){a=Math.max(0,Math.min(a,this.resolutions.length-1));if(this.map.fractionalZoom){var b=Math.floor(a),c=Math.ceil(a);a=this.resolutions[b]-(a-b)*(this.resolutions[b]-this.resolutions[c])}else a=this.resolutions[Math.round(a)];return a},getZoomForResolution:function(a,
1921 b){var c,d;if(this.map.fractionalZoom){var e=0,f=this.resolutions[e],g=this.resolutions[this.resolutions.length-1],h;c=0;for(d=this.resolutions.length;c<d;++c)if(h=this.resolutions[c],h>=a&&(f=h,e=c),h<=a){g=h;break}c=f-g;c=0<c?e+(f-a)/c:e}else{f=Number.POSITIVE_INFINITY;c=0;for(d=this.resolutions.length;c<d;c++)if(b){e=Math.abs(this.resolutions[c]-a);if(e>f)break;f=e}else if(this.resolutions[c]<a)break;c=Math.max(0,c-1)}return c},getLonLatFromViewPortPx:function(a){var b=null,c=this.map;if(null!=
1922 a&&c.minPx){var b=c.getResolution(),d=c.getMaxExtent({restricted:!0}),b=new OpenLayers.LonLat((a.x-c.minPx.x)*b+d.left,(c.minPx.y-a.y)*b+d.top);this.wrapDateLine&&(b=b.wrapDateLine(this.maxExtent))}return b},getViewPortPxFromLonLat:function(a,b){var c=null;null!=a&&(b=b||this.map.getResolution(),c=this.map.calculateBounds(null,b),c=new OpenLayers.Pixel(1/b*(a.lon-c.left),1/b*(c.top-a.lat)));return c},setOpacity:function(a){if(a!=this.opacity){this.opacity=a;for(var b=this.div.childNodes,c=0,d=b.length;c<
1923 d;++c){var e=b[c].firstChild||b[c],f=b[c].lastChild;f&&"iframe"===f.nodeName.toLowerCase()&&(e=f.parentNode);OpenLayers.Util.modifyDOMElement(e,null,null,null,null,null,null,a)}null!=this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"})}},getZIndex:function(){return this.div.style.zIndex},setZIndex:function(a){this.div.style.zIndex=a},adjustBounds:function(a){if(this.gutter){var b=this.gutter*this.map.getResolution();a=new OpenLayers.Bounds(a.left-b,a.bottom-b,a.right+
1924 b,a.top+b)}this.wrapDateLine&&(b={rightTolerance:this.getResolution(),leftTolerance:this.getResolution()},a=a.wrapDateLine(this.maxExtent,b));return a},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Layer.SphericalMercator={getExtent:function(){var a=null;return a=this.sphericalMercator?this.map.calculateBounds():OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this)},getLonLatFromViewPortPx:function(a){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments)},getViewPortPxFromLonLat:function(a){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments)},initMercatorParameters:function(){this.RESOLUTIONS=[];for(var a=0;a<=this.MAX_ZOOM_LEVEL;++a)this.RESOLUTIONS[a]=
1925 156543.03390625/Math.pow(2,a);this.units="m";this.projection=this.projection||"EPSG:900913"},forwardMercator:function(){var a=new OpenLayers.Projection("EPSG:4326"),b=new OpenLayers.Projection("EPSG:900913");return function(c,d){var e=OpenLayers.Projection.transform({x:c,y:d},a,b);return new OpenLayers.LonLat(e.x,e.y)}}(),inverseMercator:function(){var a=new OpenLayers.Projection("EPSG:4326"),b=new OpenLayers.Projection("EPSG:900913");return function(c,d){var e=OpenLayers.Projection.transform({x:c,
1926 y:d},b,a);return new OpenLayers.LonLat(e.x,e.y)}}()};OpenLayers.Layer.EventPane=OpenLayers.Class(OpenLayers.Layer,{smoothDragPan:!0,isBaseLayer:!0,isFixed:!0,pane:null,mapObject:null,initialize:function(a,b){OpenLayers.Layer.prototype.initialize.apply(this,arguments);null==this.pane&&(this.pane=OpenLayers.Util.createDiv(this.div.id+"_EventPane"))},destroy:function(){this.pane=this.mapObject=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments)},setMap:function(a){OpenLayers.Layer.prototype.setMap.apply(this,arguments);this.pane.style.zIndex=
1927 parseInt(this.div.style.zIndex)+1;this.pane.style.display=this.div.style.display;this.pane.style.width="100%";this.pane.style.height="100%";"msie"==OpenLayers.BROWSER_NAME&&(this.pane.style.background="url("+OpenLayers.Util.getImageLocation("blank.gif")+")");this.isFixed?this.map.viewPortDiv.appendChild(this.pane):this.map.layerContainerDiv.appendChild(this.pane);this.loadMapObject();null==this.mapObject&&this.loadWarningMessage()},removeMap:function(a){this.pane&&this.pane.parentNode&&this.pane.parentNode.removeChild(this.pane);
1928 OpenLayers.Layer.prototype.removeMap.apply(this,arguments)},loadWarningMessage:function(){this.div.style.backgroundColor="darkblue";var a=this.map.getSize(),b=Math.min(a.w,300),c=Math.min(a.h,200),b=new OpenLayers.Size(b,c),a=(new OpenLayers.Pixel(a.w/2,a.h/2)).add(-b.w/2,-b.h/2),a=OpenLayers.Util.createDiv(this.name+"_warning",a,b,null,null,null,"auto");a.style.padding="7px";a.style.backgroundColor="yellow";a.innerHTML=this.getWarningHTML();this.div.appendChild(a)},getWarningHTML:function(){return""},
1929 display:function(a){OpenLayers.Layer.prototype.display.apply(this,arguments);this.pane.style.display=this.div.style.display},setZIndex:function(a){OpenLayers.Layer.prototype.setZIndex.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1},moveByPx:function(a,b){OpenLayers.Layer.prototype.moveByPx.apply(this,arguments);this.dragPanMapObject?this.dragPanMapObject(a,-b):this.moveTo(this.map.getCachedCenter())},moveTo:function(a,b,c){OpenLayers.Layer.prototype.moveTo.apply(this,
1930 arguments);if(null!=this.mapObject){var d=this.map.getCenter(),e=this.map.getZoom();if(null!=d){var f=this.getMapObjectCenter(),f=this.getOLLonLatFromMapObjectLonLat(f),g=this.getMapObjectZoom(),g=this.getOLZoomFromMapObjectZoom(g);d.equals(f)&&e==g||(!b&&f&&this.dragPanMapObject&&this.smoothDragPan?(e=this.map.getViewPortPxFromLonLat(f),d=this.map.getViewPortPxFromLonLat(d),this.dragPanMapObject(d.x-e.x,e.y-d.y)):(d=this.getMapObjectLonLatFromOLLonLat(d),e=this.getMapObjectZoomFromOLZoom(e),this.setMapObjectCenter(d,
1931 e,c)))}}},getLonLatFromViewPortPx:function(a){var b=null;null!=this.mapObject&&null!=this.getMapObjectCenter()&&(a=this.getMapObjectPixelFromOLPixel(a),a=this.getMapObjectLonLatFromMapObjectPixel(a),b=this.getOLLonLatFromMapObjectLonLat(a));return b},getViewPortPxFromLonLat:function(a){var b=null;null!=this.mapObject&&null!=this.getMapObjectCenter()&&(a=this.getMapObjectLonLatFromOLLonLat(a),a=this.getMapObjectPixelFromMapObjectLonLat(a),b=this.getOLPixelFromMapObjectPixel(a));return b},getOLLonLatFromMapObjectLonLat:function(a){var b=
1932 null;null!=a&&(b=this.getLongitudeFromMapObjectLonLat(a),a=this.getLatitudeFromMapObjectLonLat(a),b=new OpenLayers.LonLat(b,a));return b},getMapObjectLonLatFromOLLonLat:function(a){var b=null;null!=a&&(b=this.getMapObjectLonLatFromLonLat(a.lon,a.lat));return b},getOLPixelFromMapObjectPixel:function(a){var b=null;null!=a&&(b=this.getXFromMapObjectPixel(a),a=this.getYFromMapObjectPixel(a),b=new OpenLayers.Pixel(b,a));return b},getMapObjectPixelFromOLPixel:function(a){var b=null;null!=a&&(b=this.getMapObjectPixelFromXY(a.x,
1933 a.y));return b},CLASS_NAME:"OpenLayers.Layer.EventPane"});OpenLayers.Layer.FixedZoomLevels=OpenLayers.Class({initialize:function(){},initResolutions:function(){for(var a=["minZoomLevel","maxZoomLevel","numZoomLevels"],b=0,c=a.length;b<c;b++){var d=a[b];this[d]=null!=this.options[d]?this.options[d]:this.map[d]}if(null==this.minZoomLevel||this.minZoomLevel<this.MIN_ZOOM_LEVEL)this.minZoomLevel=this.MIN_ZOOM_LEVEL;a=this.MAX_ZOOM_LEVEL-this.minZoomLevel+1;b=null==this.options.numZoomLevels&&null!=this.options.maxZoomLevel||null==this.numZoomLevels&&null!=this.maxZoomLevel?
1934 this.maxZoomLevel-this.minZoomLevel+1:this.numZoomLevels;this.numZoomLevels=null!=b?Math.min(b,a):a;this.maxZoomLevel=this.minZoomLevel+this.numZoomLevels-1;if(null!=this.RESOLUTIONS){a=0;this.resolutions=[];for(b=this.minZoomLevel;b<=this.maxZoomLevel;b++)this.resolutions[a++]=this.RESOLUTIONS[b];this.maxResolution=this.resolutions[0];this.minResolution=this.resolutions[this.resolutions.length-1]}},getResolution:function(){if(null!=this.resolutions)return OpenLayers.Layer.prototype.getResolution.apply(this,
1935 arguments);var a=null,b=this.map.getSize(),c=this.getExtent();null!=b&&null!=c&&(a=Math.max(c.getWidth()/b.w,c.getHeight()/b.h));return a},getExtent:function(){var a=this.map.getSize(),b=this.getLonLatFromViewPortPx({x:0,y:0}),a=this.getLonLatFromViewPortPx({x:a.w,y:a.h});return null!=b&&null!=a?new OpenLayers.Bounds(b.lon,a.lat,a.lon,b.lat):null},getZoomForResolution:function(a){if(null!=this.resolutions)return OpenLayers.Layer.prototype.getZoomForResolution.apply(this,arguments);var b=OpenLayers.Layer.prototype.getExtent.apply(this,
1936 []);return this.getZoomForExtent(b)},getOLZoomFromMapObjectZoom:function(a){var b=null;null!=a&&(b=a-this.minZoomLevel,this.map.baseLayer!==this&&(b=this.map.baseLayer.getZoomForResolution(this.getResolutionForZoom(b))));return b},getMapObjectZoomFromOLZoom:function(a){var b=null;null!=a&&(b=a+this.minZoomLevel,this.map.baseLayer!==this&&(b=this.getZoomForResolution(this.map.baseLayer.getResolutionForZoom(b))));return b},CLASS_NAME:"OpenLayers.Layer.FixedZoomLevels"});OpenLayers.Layer.Google=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:21,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,6.866455078125E-4,3.4332275390625E-4,1.71661376953125E-4,8.58306884765625E-5,4.291534423828125E-5,2.145767211914062E-5,1.072883605957031E-5,5.36441802978515E-6,2.68220901489257E-6,1.341104507446289E-6,6.705522537231445E-7],
1937 type:null,wrapDateLine:!0,sphericalMercator:!1,version:null,initialize:function(a,b){b=b||{};b.version||(b.version="function"===typeof GMap2?"2":"3");var c=OpenLayers.Layer.Google["v"+b.version.replace(/\./g,"_")];if(c)OpenLayers.Util.applyDefaults(b,c);else throw"Unsupported Google Maps API version: "+b.version;OpenLayers.Util.applyDefaults(b,c.DEFAULTS);b.maxExtent&&(b.maxExtent=b.maxExtent.clone());OpenLayers.Layer.EventPane.prototype.initialize.apply(this,[a,b]);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,
1938 [a,b]);this.sphericalMercator&&(OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator),this.initMercatorParameters())},clone:function(){return new OpenLayers.Layer.Google(this.name,this.getOptions())},setVisibility:function(a){var b=null==this.opacity?1:this.opacity;OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this,arguments);this.setOpacity(b)},display:function(a){this._dragging||this.setGMapVisibility(a);OpenLayers.Layer.EventPane.prototype.display.apply(this,arguments)},moveTo:function(a,
1939 b,c){this._dragging=c;OpenLayers.Layer.EventPane.prototype.moveTo.apply(this,arguments);delete this._dragging},setOpacity:function(a){a!==this.opacity&&(null!=this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"}),this.opacity=a);if(this.getVisibility()){var b=this.getMapContainer();OpenLayers.Util.modifyDOMElement(b,null,null,null,null,null,null,a)}},destroy:function(){if(this.map){this.setGMapVisibility(!1);var a=OpenLayers.Layer.Google.cache[this.map.id];a&&1>=a.count&&
1940 this.removeGMapElements()}OpenLayers.Layer.EventPane.prototype.destroy.apply(this,arguments)},removeGMapElements:function(){var a=OpenLayers.Layer.Google.cache[this.map.id];if(a){var b=this.mapObject&&this.getMapContainer();b&&b.parentNode&&b.parentNode.removeChild(b);(b=a.termsOfUse)&&b.parentNode&&b.parentNode.removeChild(b);(a=a.poweredBy)&&a.parentNode&&a.parentNode.removeChild(a);this.mapObject&&(window.google&&google.maps&&google.maps.event&&google.maps.event.clearListeners)&&google.maps.event.clearListeners(this.mapObject,
1941 "tilesloaded")}},removeMap:function(a){this.visibility&&this.mapObject&&this.setGMapVisibility(!1);var b=OpenLayers.Layer.Google.cache[a.id];b&&(1>=b.count?(this.removeGMapElements(),delete OpenLayers.Layer.Google.cache[a.id]):--b.count);delete this.termsOfUse;delete this.poweredBy;delete this.mapObject;delete this.dragObject;OpenLayers.Layer.EventPane.prototype.removeMap.apply(this,arguments)},getOLBoundsFromMapObjectBounds:function(a){var b=null;null!=a&&(b=a.getSouthWest(),a=a.getNorthEast(),this.sphericalMercator?
1942 (b=this.forwardMercator(b.lng(),b.lat()),a=this.forwardMercator(a.lng(),a.lat())):(b=new OpenLayers.LonLat(b.lng(),b.lat()),a=new OpenLayers.LonLat(a.lng(),a.lat())),b=new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat));return b},getWarningHTML:function(){return OpenLayers.i18n("googleWarning")},getMapObjectCenter:function(){return this.mapObject.getCenter()},getMapObjectZoom:function(){return this.mapObject.getZoom()},getLongitudeFromMapObjectLonLat:function(a){return this.sphericalMercator?this.forwardMercator(a.lng(),
1943 a.lat()).lon:a.lng()},getLatitudeFromMapObjectLonLat:function(a){return this.sphericalMercator?this.forwardMercator(a.lng(),a.lat()).lat:a.lat()},getXFromMapObjectPixel:function(a){return a.x},getYFromMapObjectPixel:function(a){return a.y},CLASS_NAME:"OpenLayers.Layer.Google"});OpenLayers.Layer.Google.cache={};
1944 OpenLayers.Layer.Google.v2={termsOfUse:null,poweredBy:null,dragObject:null,loadMapObject:function(){this.type||(this.type=G_NORMAL_MAP);var a,b,c,d=OpenLayers.Layer.Google.cache[this.map.id];if(d)a=d.mapObject,b=d.termsOfUse,c=d.poweredBy,++d.count;else{var d=this.map.viewPortDiv,e=document.createElement("div");e.id=this.map.id+"_GMap2Container";e.style.position="absolute";e.style.width="100%";e.style.height="100%";d.appendChild(e);try{a=new GMap2(e),b=e.lastChild,d.appendChild(b),b.style.zIndex=
1945 "1100",b.style.right="",b.style.bottom="",b.className="olLayerGoogleCopyright",c=e.lastChild,d.appendChild(c),c.style.zIndex="1100",c.style.right="",c.style.bottom="",c.className="olLayerGooglePoweredBy gmnoprint"}catch(f){throw f;}OpenLayers.Layer.Google.cache[this.map.id]={mapObject:a,termsOfUse:b,poweredBy:c,count:1}}this.mapObject=a;this.termsOfUse=b;this.poweredBy=c;-1===OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),this.type)&&this.mapObject.addMapType(this.type);"function"==typeof a.getDragObject?
1946 this.dragObject=a.getDragObject():this.dragPanMapObject=null;!1===this.isBaseLayer&&this.setGMapVisibility("none"!==this.div.style.display)},onMapResize:function(){if(this.visibility&&this.mapObject.isLoaded())this.mapObject.checkResize();else{if(!this._resized)var a=this,b=GEvent.addListener(this.mapObject,"load",function(){GEvent.removeListener(b);delete a._resized;a.mapObject.checkResize();a.moveTo(a.map.getCenter(),a.map.getZoom())});this._resized=!0}},setGMapVisibility:function(a){var b=OpenLayers.Layer.Google.cache[this.map.id];
1947 if(b){var c=this.mapObject.getContainer();!0===a?(this.mapObject.setMapType(this.type),c.style.display="",this.termsOfUse.style.left="",this.termsOfUse.style.display="",this.poweredBy.style.display="",b.displayed=this.id):(b.displayed===this.id&&delete b.displayed,b.displayed||(c.style.display="none",this.termsOfUse.style.display="none",this.termsOfUse.style.left="-9999px",this.poweredBy.style.display="none"))}},getMapContainer:function(){return this.mapObject.getContainer()},getMapObjectBoundsFromOLBounds:function(a){var b=
1948 null;null!=a&&(b=this.sphericalMercator?this.inverseMercator(a.bottom,a.left):new OpenLayers.LonLat(a.bottom,a.left),a=this.sphericalMercator?this.inverseMercator(a.top,a.right):new OpenLayers.LonLat(a.top,a.right),b=new GLatLngBounds(new GLatLng(b.lat,b.lon),new GLatLng(a.lat,a.lon)));return b},setMapObjectCenter:function(a,b){this.mapObject.setCenter(a,b)},dragPanMapObject:function(a,b){this.dragObject.moveBy(new GSize(-a,b))},getMapObjectLonLatFromMapObjectPixel:function(a){return this.mapObject.fromContainerPixelToLatLng(a)},
1949 getMapObjectPixelFromMapObjectLonLat:function(a){return this.mapObject.fromLatLngToContainerPixel(a)},getMapObjectZoomFromMapObjectBounds:function(a){return this.mapObject.getBoundsZoomLevel(a)},getMapObjectLonLatFromLonLat:function(a,b){var c;this.sphericalMercator?(c=this.inverseMercator(a,b),c=new GLatLng(c.lat,c.lon)):c=new GLatLng(b,a);return c},getMapObjectPixelFromXY:function(a,b){return new GPoint(a,b)}};OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(a){window.ActiveXObject&&(this.xmldom=new ActiveXObject("Microsoft.XMLDOM"));OpenLayers.Format.prototype.initialize.apply(this,[a]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var b in this.namespaces)this.namespaceAlias[this.namespaces[b]]=b},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,
1950 arguments)},setNamespace:function(a,b){this.namespaces[a]=b;this.namespaceAlias[b]=a},read:function(a){var b=a.indexOf("<");0<b&&(a=a.substring(b));b=OpenLayers.Util.Try(OpenLayers.Function.bind(function(){var b;b=window.ActiveXObject&&!this.xmldom?new ActiveXObject("Microsoft.XMLDOM"):this.xmldom;b.loadXML(a);return b},this),function(){return(new DOMParser).parseFromString(a,"text/xml")},function(){var b=new XMLHttpRequest;b.open("GET","data:text/xml;charset=utf-8,"+encodeURIComponent(a),!1);b.overrideMimeType&&
1951 b.overrideMimeType("text/xml");b.send(null);return b.responseXML});this.keepData&&(this.data=b);return b},write:function(a){if(this.xmldom)a=a.xml;else{var b=new XMLSerializer;if(1==a.nodeType){var c=document.implementation.createDocument("","",null);c.importNode&&(a=c.importNode(a,!0));c.appendChild(a);a=b.serializeToString(c)}else a=b.serializeToString(a)}return a},createElementNS:function(a,b){return this.xmldom?"string"==typeof a?this.xmldom.createNode(1,b,a):this.xmldom.createNode(1,b,""):document.createElementNS(a,
1952 b)},createDocumentFragment:function(){return this.xmldom?this.xmldom.createDocumentFragment():document.createDocumentFragment()},createTextNode:function(a){"string"!==typeof a&&(a=String(a));return this.xmldom?this.xmldom.createTextNode(a):document.createTextNode(a)},getElementsByTagNameNS:function(a,b,c){var d=[];if(a.getElementsByTagNameNS)d=a.getElementsByTagNameNS(b,c);else{a=a.getElementsByTagName("*");for(var e,f,g=0,h=a.length;g<h;++g)if(e=a[g],f=e.prefix?e.prefix+":"+c:c,"*"==c||f==e.nodeName)"*"!=
1953 b&&b!=e.namespaceURI||d.push(e)}return d},getAttributeNodeNS:function(a,b,c){var d=null;if(a.getAttributeNodeNS)d=a.getAttributeNodeNS(b,c);else{a=a.attributes;for(var e,f,g=0,h=a.length;g<h;++g)if(e=a[g],e.namespaceURI==b&&(f=e.prefix?e.prefix+":"+c:c,f==e.nodeName)){d=e;break}}return d},getAttributeNS:function(a,b,c){var d="";if(a.getAttributeNS)d=a.getAttributeNS(b,c)||"";else if(a=this.getAttributeNodeNS(a,b,c))d=a.nodeValue;return d},getChildValue:function(a,b){var c=b||"";if(a)for(var d=a.firstChild;d;d=
1954 d.nextSibling)switch(d.nodeType){case 3:case 4:c+=d.nodeValue}return c},isSimpleContent:function(a){var b=!0;for(a=a.firstChild;a;a=a.nextSibling)if(1===a.nodeType){b=!1;break}return b},contentType:function(a){var b=!1,c=!1,d=OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;for(a=a.firstChild;a;a=a.nextSibling){switch(a.nodeType){case 1:c=!0;break;case 8:break;default:b=!0}if(c&&b)break}if(c&&b)d=OpenLayers.Format.XML.CONTENT_TYPE.MIXED;else{if(c)return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;if(b)return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE}return d},
1955 hasAttributeNS:function(a,b,c){var d=!1;return d=a.hasAttributeNS?a.hasAttributeNS(b,c):!!this.getAttributeNodeNS(a,b,c)},setAttributeNS:function(a,b,c,d){if(a.setAttributeNS)a.setAttributeNS(b,c,d);else if(this.xmldom)b?(b=a.ownerDocument.createNode(2,c,b),b.nodeValue=d,a.setAttributeNode(b)):a.setAttribute(c,d);else throw"setAttributeNS not implemented";},createElementNSPlus:function(a,b){b=b||{};var c=b.uri||this.namespaces[b.prefix];c||(c=a.indexOf(":"),c=this.namespaces[a.substring(0,c)]);c||
1956 (c=this.namespaces[this.defaultPrefix]);c=this.createElementNS(c,a);b.attributes&&this.setAttributes(c,b.attributes);var d=b.value;null!=d&&c.appendChild(this.createTextNode(d));return c},setAttributes:function(a,b){var c,d,e;for(e in b)null!=b[e]&&b[e].toString&&(c=b[e].toString(),d=this.namespaces[e.substring(0,e.indexOf(":"))]||null,this.setAttributeNS(a,d,e,c))},readNode:function(a,b){b||(b={});var c=this.readers[a.namespaceURI?this.namespaceAlias[a.namespaceURI]:this.defaultPrefix];if(c){var d=
1957 a.localName||a.nodeName.split(":").pop();(c=c[d]||c["*"])&&c.apply(this,[a,b])}return b},readChildNodes:function(a,b){b||(b={});for(var c=a.childNodes,d,e=0,f=c.length;e<f;++e)d=c[e],1==d.nodeType&&this.readNode(d,b);return b},writeNode:function(a,b,c){var d,e=a.indexOf(":");0<e?(d=a.substring(0,e),a=a.substring(e+1)):d=c?this.namespaceAlias[c.namespaceURI]:this.defaultPrefix;b=this.writers[d][a].apply(this,[b]);c&&c.appendChild(b);return b},getChildEl:function(a,b,c){return a&&this.getThisOrNextEl(a.firstChild,
1958 b,c)},getNextEl:function(a,b,c){return a&&this.getThisOrNextEl(a.nextSibling,b,c)},getThisOrNextEl:function(a,b,c){a:for(;a;a=a.nextSibling)switch(a.nodeType){case 1:if(!(b&&b!==(a.localName||a.nodeName.split(":").pop())||c&&c!==a.namespaceURI))break a;a=null;break a;case 3:if(/^\s*$/.test(a.nodeValue))break;case 4:case 6:case 12:case 10:case 11:a=null;break a}return a||null},lookupNamespaceURI:function(a,b){var c=null;if(a)if(a.lookupNamespaceURI)c=a.lookupNamespaceURI(b);else a:switch(a.nodeType){case 1:if(null!==
1959 a.namespaceURI&&a.prefix===b){c=a.namespaceURI;break a}if(c=a.attributes.length)for(var d,e=0;e<c;++e)if(d=a.attributes[e],"xmlns"===d.prefix&&d.name==="xmlns:"+b){c=d.value||null;break a}else if("xmlns"===d.name&&null===b){c=d.value||null;break a}c=this.lookupNamespaceURI(a.parentNode,b);break a;case 2:c=this.lookupNamespaceURI(a.ownerElement,b);break a;case 9:c=this.lookupNamespaceURI(a.documentElement,b);break a;case 6:case 12:case 10:case 11:break a;default:c=this.lookupNamespaceURI(a.parentNode,
1960 b)}return c},getXMLDoc:function(){OpenLayers.Format.XML.document||this.xmldom||(document.implementation&&document.implementation.createDocument?OpenLayers.Format.XML.document=document.implementation.createDocument("","",null):!this.xmldom&&window.ActiveXObject&&(this.xmldom=new ActiveXObject("Microsoft.XMLDOM")));return OpenLayers.Format.XML.document||this.xmldom},CLASS_NAME:"OpenLayers.Format.XML"});OpenLayers.Format.XML.CONTENT_TYPE={EMPTY:0,SIMPLE:1,COMPLEX:2,MIXED:3};
1961 OpenLayers.Format.XML.lookupNamespaceURI=OpenLayers.Function.bind(OpenLayers.Format.XML.prototype.lookupNamespaceURI,OpenLayers.Format.XML.prototype);OpenLayers.Format.XML.document=null;OpenLayers.Format.WFST=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Format.WFST.DEFAULTS);var b=OpenLayers.Format.WFST["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported WFST version: "+a.version;return new b(a)};OpenLayers.Format.WFST.DEFAULTS={version:"1.0.0"};OpenLayers.Feature=OpenLayers.Class({layer:null,id:null,lonlat:null,data:null,marker:null,popupClass:null,popup:null,initialize:function(a,b,c){this.layer=a;this.lonlat=b;this.data=null!=c?c:{};this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){null!=this.layer&&null!=this.layer.map&&null!=this.popup&&this.layer.map.removePopup(this.popup);null!=this.layer&&null!=this.marker&&this.layer.removeMarker(this.marker);this.data=this.lonlat=this.id=this.layer=null;null!=this.marker&&
1962 (this.destroyMarker(this.marker),this.marker=null);null!=this.popup&&(this.destroyPopup(this.popup),this.popup=null)},onScreen:function(){var a=!1;null!=this.layer&&null!=this.layer.map&&(a=this.layer.map.getExtent().containsLonLat(this.lonlat));return a},createMarker:function(){null!=this.lonlat&&(this.marker=new OpenLayers.Marker(this.lonlat,this.data.icon));return this.marker},destroyMarker:function(){this.marker.destroy()},createPopup:function(a){null!=this.lonlat&&(this.popup||(this.popup=new (this.popupClass?
1963 this.popupClass:OpenLayers.Popup.Anchored)(this.id+"_popup",this.lonlat,this.data.popupSize,this.data.popupContentHTML,this.marker?this.marker.icon:null,a)),null!=this.data.overflow&&(this.popup.contentDiv.style.overflow=this.data.overflow),this.popup.feature=this);return this.popup},destroyPopup:function(){this.popup&&(this.popup.feature=null,this.popup.destroy(),this.popup=null)},CLASS_NAME:"OpenLayers.Feature"});OpenLayers.State={UNKNOWN:"Unknown",INSERT:"Insert",UPDATE:"Update",DELETE:"Delete"};
1964 OpenLayers.Feature.Vector=OpenLayers.Class(OpenLayers.Feature,{fid:null,geometry:null,attributes:null,bounds:null,state:null,style:null,url:null,renderIntent:"default",modified:null,initialize:function(a,b,c){OpenLayers.Feature.prototype.initialize.apply(this,[null,null,b]);this.lonlat=null;this.geometry=a?a:null;this.state=null;this.attributes={};b&&(this.attributes=OpenLayers.Util.extend(this.attributes,b));this.style=c?c:null},destroy:function(){this.layer&&(this.layer.removeFeatures(this),this.layer=
1965 null);this.modified=this.geometry=null;OpenLayers.Feature.prototype.destroy.apply(this,arguments)},clone:function(){return new OpenLayers.Feature.Vector(this.geometry?this.geometry.clone():null,this.attributes,this.style)},onScreen:function(a){var b=!1;this.layer&&this.layer.map&&(b=this.layer.map.getExtent(),a?(a=this.geometry.getBounds(),b=b.intersectsBounds(a)):b=b.toGeometry().intersects(this.geometry));return b},getVisibility:function(){return!(this.style&&"none"==this.style.display||!this.layer||
1966 this.layer&&this.layer.styleMap&&"none"==this.layer.styleMap.createSymbolizer(this,this.renderIntent).display||this.layer&&!this.layer.getVisibility())},createMarker:function(){return null},destroyMarker:function(){},createPopup:function(){return null},atPoint:function(a,b,c){var d=!1;this.geometry&&(d=this.geometry.atPoint(a,b,c));return d},destroyPopup:function(){},move:function(a){if(this.layer&&this.geometry.move){a="OpenLayers.LonLat"==a.CLASS_NAME?this.layer.getViewPortPxFromLonLat(a):a;var b=
1967 this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat()),c=this.layer.map.getResolution();this.geometry.move(c*(a.x-b.x),c*(b.y-a.y));this.layer.drawFeature(this);return b}},toState:function(a){if(a==OpenLayers.State.UPDATE)switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.DELETE:this.state=a}else if(a==OpenLayers.State.INSERT)switch(this.state){case OpenLayers.State.UNKNOWN:break;default:this.state=a}else if(a==OpenLayers.State.DELETE)switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.UPDATE:this.state=
1968 a}else a==OpenLayers.State.UNKNOWN&&(this.state=a)},CLASS_NAME:"OpenLayers.Feature.Vector"});
1969 OpenLayers.Feature.Vector.style={"default":{fillColor:"#ee9900",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#ee9900",strokeOpacity:1,strokeWidth:1,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},select:{fillColor:"blue",fillOpacity:0.4,
1970 hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"blue",strokeOpacity:1,strokeWidth:2,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"pointer",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},temporary:{fillColor:"#66cccc",fillOpacity:0.2,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#66cccc",strokeOpacity:1,
1971 strokeLinecap:"round",strokeWidth:2,strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},"delete":{display:"none"}};OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:!1,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:!1,propertyStyles:null,initialize:function(a,b){OpenLayers.Util.extend(this,b);this.rules=[];b&&b.rules&&this.addRules(b.rules);this.setDefaultStyle(a||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){for(var a=0,b=this.rules.length;a<b;a++)this.rules[a].destroy(),
1972 this.rules[a]=null;this.defaultStyle=this.rules=null},createSymbolizer:function(a){for(var b=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),a),c=this.rules,d,e=[],f=!1,g=0,h=c.length;g<h;g++)d=c[g],d.evaluate(a)&&(d instanceof OpenLayers.Rule&&d.elseFilter?e.push(d):(f=!0,this.applySymbolizer(d,b,a)));if(!1==f&&0<e.length)for(f=!0,g=0,h=e.length;g<h;g++)this.applySymbolizer(e[g],b,a);0<c.length&&!1==f&&(b.display="none");null!=b.label&&"string"!==typeof b.label&&
1973 (b.label=String(b.label));return b},applySymbolizer:function(a,b,c){var d=c.geometry?this.getSymbolizerPrefix(c.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];a=a.symbolizer[d]||a.symbolizer;!0===this.defaultsPerSymbolizer&&(d=this.defaultStyle,OpenLayers.Util.applyDefaults(a,{pointRadius:d.pointRadius}),!0!==a.stroke&&!0!==a.graphic||OpenLayers.Util.applyDefaults(a,{strokeWidth:d.strokeWidth,strokeColor:d.strokeColor,strokeOpacity:d.strokeOpacity,strokeDashstyle:d.strokeDashstyle,strokeLinecap:d.strokeLinecap}),
1974 !0!==a.fill&&!0!==a.graphic||OpenLayers.Util.applyDefaults(a,{fillColor:d.fillColor,fillOpacity:d.fillOpacity}),!0===a.graphic&&OpenLayers.Util.applyDefaults(a,{pointRadius:this.defaultStyle.pointRadius,externalGraphic:this.defaultStyle.externalGraphic,graphicName:this.defaultStyle.graphicName,graphicOpacity:this.defaultStyle.graphicOpacity,graphicWidth:this.defaultStyle.graphicWidth,graphicHeight:this.defaultStyle.graphicHeight,graphicXOffset:this.defaultStyle.graphicXOffset,graphicYOffset:this.defaultStyle.graphicYOffset}));
1975 return this.createLiterals(OpenLayers.Util.extend(b,a),c)},createLiterals:function(a,b){var c=OpenLayers.Util.extend({},b.attributes||b.data);OpenLayers.Util.extend(c,this.context);for(var d in this.propertyStyles)a[d]=OpenLayers.Style.createLiteral(a[d],c,b,d);return a},findPropertyStyles:function(){var a={};this.addPropertyStyles(a,this.defaultStyle);for(var b=this.rules,c,d,e=0,f=b.length;e<f;e++){c=b[e].symbolizer;for(var g in c)if(d=c[g],"object"==typeof d)this.addPropertyStyles(a,d);else{this.addPropertyStyles(a,
1976 c);break}}return a},addPropertyStyles:function(a,b){var c,d;for(d in b)c=b[d],"string"==typeof c&&c.match(/\$\{\w+\}/)&&(a[d]=!0);return a},addRules:function(a){Array.prototype.push.apply(this.rules,a);this.propertyStyles=this.findPropertyStyles()},setDefaultStyle:function(a){this.defaultStyle=a;this.propertyStyles=this.findPropertyStyles()},getSymbolizerPrefix:function(a){for(var b=OpenLayers.Style.SYMBOLIZER_PREFIXES,c=0,d=b.length;c<d;c++)if(-1!=a.CLASS_NAME.indexOf(b[c]))return b[c]},clone:function(){var a=
1977 OpenLayers.Util.extend({},this);if(this.rules){a.rules=[];for(var b=0,c=this.rules.length;b<c;++b)a.rules.push(this.rules[b].clone())}a.context=this.context&&OpenLayers.Util.extend({},this.context);b=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(b,a)},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(a,b,c,d){"string"==typeof a&&-1!=a.indexOf("${")&&(a=OpenLayers.String.format(a,b,[c,d]),a=isNaN(a)||!a?a:parseFloat(a));return a};
1978 OpenLayers.Style.SYMBOLIZER_PREFIXES=["Point","Line","Polygon","Text","Raster"];OpenLayers.Filter=OpenLayers.Class({initialize:function(a){OpenLayers.Util.extend(this,a)},destroy:function(){},evaluate:function(a){return!0},clone:function(){return null},toString:function(){return OpenLayers.Format&&OpenLayers.Format.CQL?OpenLayers.Format.CQL.prototype.write(this):Object.prototype.toString.call(this)},CLASS_NAME:"OpenLayers.Filter"});OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,evaluate:function(a){var b=!1;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(a.geometry){var c=this.value;"OpenLayers.Bounds"==this.value.CLASS_NAME&&(c=this.value.toGeometry());a.geometry.intersects(c)&&(b=!0)}break;default:throw Error("evaluate is not implemented for this filter type.");}return b},clone:function(){var a=
1979 OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(a)},CLASS_NAME:"OpenLayers.Filter.Spatial"});OpenLayers.Filter.Spatial.BBOX="BBOX";OpenLayers.Filter.Spatial.INTERSECTS="INTERSECTS";OpenLayers.Filter.Spatial.DWITHIN="DWITHIN";OpenLayers.Filter.Spatial.WITHIN="WITHIN";OpenLayers.Filter.Spatial.CONTAINS="CONTAINS";OpenLayers.Filter.FeatureId=OpenLayers.Class(OpenLayers.Filter,{fids:null,type:"FID",initialize:function(a){this.fids=[];OpenLayers.Filter.prototype.initialize.apply(this,[a])},evaluate:function(a){for(var b=0,c=this.fids.length;b<c;b++)if((a.fid||a.id)==this.fids[b])return!0;return!1},clone:function(){var a=new OpenLayers.Filter.FeatureId;OpenLayers.Util.extend(a,this);a.fids=this.fids.slice();return a},CLASS_NAME:"OpenLayers.Filter.FeatureId"});OpenLayers.Format.WFST.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs",gml:"http://www.opengis.net/gml",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows"},defaultPrefix:"wfs",version:null,schemaLocations:null,srsName:null,extractAttributes:!0,xy:!0,stateName:null,initialize:function(a){this.stateName={};this.stateName[OpenLayers.State.INSERT]="wfs:Insert";this.stateName[OpenLayers.State.UPDATE]=
1980 "wfs:Update";this.stateName[OpenLayers.State.DELETE]="wfs:Delete";OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},getSrsName:function(a,b){var c=b&&b.srsName;c||(c=a&&a.layer?a.layer.projection.getCode():this.srsName);return c},read:function(a,b){b=b||{};OpenLayers.Util.applyDefaults(b,{output:"features"});"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var c={};a&&this.readNode(a,c,!0);c.features&&"features"===b.output&&
1981 (c=c.features);return c},readers:{wfs:{FeatureCollection:function(a,b){b.features=[];this.readChildNodes(a,b)}}},write:function(a,b){var c=this.writeNode("wfs:Transaction",{features:a,options:b}),d=this.schemaLocationAttr();d&&this.setAttributeNS(c,this.namespaces.xsi,"xsi:schemaLocation",d);return OpenLayers.Format.XML.prototype.write.apply(this,[c])},writers:{wfs:{GetFeature:function(a){var b=this.createElementNSPlus("wfs:GetFeature",{attributes:{service:"WFS",version:this.version,handle:a&&a.handle,
1982 outputFormat:a&&a.outputFormat,maxFeatures:a&&a.maxFeatures,"xsi:schemaLocation":this.schemaLocationAttr(a)}});if("string"==typeof this.featureType)this.writeNode("Query",a,b);else for(var c=0,d=this.featureType.length;c<d;c++)a.featureType=this.featureType[c],this.writeNode("Query",a,b);return b},Transaction:function(a){a=a||{};var b=a.options||{},c=this.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version,handle:b.handle}}),d,e=a.features;if(e){!0===b.multi&&OpenLayers.Util.extend(this.geometryTypes,
1983 {"OpenLayers.Geometry.Point":"MultiPoint","OpenLayers.Geometry.LineString":!0===this.multiCurve?"MultiCurve":"MultiLineString","OpenLayers.Geometry.Polygon":!0===this.multiSurface?"MultiSurface":"MultiPolygon"});var f,g;a=0;for(d=e.length;a<d;++a)g=e[a],(f=this.stateName[g.state])&&this.writeNode(f,{feature:g,options:b},c);!0===b.multi&&this.setGeometryTypes()}if(b.nativeElements)for(a=0,d=b.nativeElements.length;a<d;++a)this.writeNode("wfs:Native",b.nativeElements[a],c);return c},Native:function(a){return this.createElementNSPlus("wfs:Native",
1984 {attributes:{vendorId:a.vendorId,safeToIgnore:a.safeToIgnore},value:a.value})},Insert:function(a){var b=a.feature;a=a.options;a=this.createElementNSPlus("wfs:Insert",{attributes:{handle:a&&a.handle}});this.srsName=this.getSrsName(b);this.writeNode("feature:_typeName",b,a);return a},Update:function(a){var b=a.feature;a=a.options;a=this.createElementNSPlus("wfs:Update",{attributes:{handle:a&&a.handle,typeName:(this.featureNS?this.featurePrefix+":":"")+this.featureType}});this.featureNS&&a.setAttribute("xmlns:"+
1985 this.featurePrefix,this.featureNS);var c=b.modified;null===this.geometryName||c&&void 0===c.geometry||(this.srsName=this.getSrsName(b),this.writeNode("Property",{name:this.geometryName,value:b.geometry},a));for(var d in b.attributes)void 0===b.attributes[d]||c&&c.attributes&&(!c.attributes||void 0===c.attributes[d])||this.writeNode("Property",{name:d,value:b.attributes[d]},a);this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[b.fid]}),a);return a},Property:function(a){var b=this.createElementNSPlus("wfs:Property");
1986 this.writeNode("Name",a.name,b);null!==a.value&&this.writeNode("Value",a.value,b);return b},Name:function(a){return this.createElementNSPlus("wfs:Name",{value:a})},Value:function(a){var b;a instanceof OpenLayers.Geometry?(b=this.createElementNSPlus("wfs:Value"),a=this.writeNode("feature:_geometry",a).firstChild,b.appendChild(a)):b=this.createElementNSPlus("wfs:Value",{value:a});return b},Delete:function(a){var b=a.feature;a=a.options;a=this.createElementNSPlus("wfs:Delete",{attributes:{handle:a&&
1987 a.handle,typeName:(this.featureNS?this.featurePrefix+":":"")+this.featureType}});this.featureNS&&a.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[b.fid]}),a);return a}}},schemaLocationAttr:function(a){a=OpenLayers.Util.extend({featurePrefix:this.featurePrefix,schema:this.schema},a);var b=OpenLayers.Util.extend({},this.schemaLocations);a.schema&&(b[a.featurePrefix]=a.schema);a=[];var c,d;for(d in b)(c=this.namespaces[d])&&
1988 a.push(c+" "+b[d]);return a.join(" ")||void 0},setFilterProperty:function(a){if(a.filters)for(var b=0,c=a.filters.length;b<c;++b)OpenLayers.Format.WFST.v1.prototype.setFilterProperty.call(this,a.filters[b]);else a instanceof OpenLayers.Filter.Spatial&&!a.property&&(a.property=this.geometryName)},CLASS_NAME:"OpenLayers.Format.WFST.v1"});OpenLayers.Format.OGCExceptionReport=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},defaultPrefix:"ogc",read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b={exceptionReport:null};a.documentElement&&(this.readChildNodes(a,b),null===b.exceptionReport&&(b=(new OpenLayers.Format.OWSCommon).read(a)));return b},readers:{ogc:{ServiceExceptionReport:function(a,
1989 b){b.exceptionReport={exceptions:[]};this.readChildNodes(a,b.exceptionReport)},ServiceException:function(a,b){var c={code:a.getAttribute("code"),locator:a.getAttribute("locator"),text:this.getChildValue(a)};b.exceptions.push(c)}}},CLASS_NAME:"OpenLayers.Format.OGCExceptionReport"});OpenLayers.Format.XML.VersionedOGC=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:null,version:null,profile:null,allowFallback:!1,name:null,stringifyOutput:!1,parser:null,initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a]);a=this.CLASS_NAME;this.name=a.substring(a.lastIndexOf(".")+1)},getVersion:function(a,b){var c;a?(c=this.version,c||(c=a.getAttribute("version"),c||(c=this.defaultVersion))):c=b&&b.version||this.version||this.defaultVersion;return c},getParser:function(a){a=
1990 a||this.defaultVersion;var b=this.profile?"_"+this.profile:"";if(!this.parser||this.parser.VERSION!=a){var c=OpenLayers.Format[this.name]["v"+a.replace(/\./g,"_")+b];if(!c&&(""!==b&&this.allowFallback&&(b="",c=OpenLayers.Format[this.name]["v"+a.replace(/\./g,"_")]),!c))throw"Can't find a "+this.name+" parser for version "+a+b;this.parser=new c(this.options)}return this.parser},write:function(a,b){var c=this.getVersion(null,b);this.parser=this.getParser(c);c=this.parser.write(a,b);return!1===this.stringifyOutput?
1991 c:OpenLayers.Format.XML.prototype.write.apply(this,[c])},read:function(a,b){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var c=this.getVersion(a.documentElement);this.parser=this.getParser(c);var d=this.parser.read(a,b),e=this.parser.errorProperty||null;null!==e&&void 0===d[e]&&(e=new OpenLayers.Format.OGCExceptionReport,d.error=e.read(a));d.version=c;return d},CLASS_NAME:"OpenLayers.Format.XML.VersionedOGC"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(a){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[a])},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this)},evaluate:function(a){var b,c;switch(this.type){case OpenLayers.Filter.Logical.AND:b=0;for(c=this.filters.length;b<c;b++)if(!1==this.filters[b].evaluate(a))return!1;return!0;case OpenLayers.Filter.Logical.OR:b=0;for(c=this.filters.length;b<
1992 c;b++)if(!0==this.filters[b].evaluate(a))return!0;return!1;case OpenLayers.Filter.Logical.NOT:return!this.filters[0].evaluate(a)}},clone:function(){for(var a=[],b=0,c=this.filters.length;b<c;++b)a.push(this.filters[b].clone());return new OpenLayers.Filter.Logical({type:this.type,filters:a})},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:!0,lowerBoundary:null,upperBoundary:null,initialize:function(a){OpenLayers.Filter.prototype.initialize.apply(this,[a]);this.type===OpenLayers.Filter.Comparison.LIKE&&void 0===a.matchCase&&(this.matchCase=null)},evaluate:function(a){a instanceof OpenLayers.Feature.Vector&&(a=a.attributes);var b=!1;a=a[this.property];switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:b=this.value;
1993 b=this.matchCase||"string"!=typeof a||"string"!=typeof b?a==b:a.toUpperCase()==b.toUpperCase();break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:b=this.value;b=this.matchCase||"string"!=typeof a||"string"!=typeof b?a!=b:a.toUpperCase()!=b.toUpperCase();break;case OpenLayers.Filter.Comparison.LESS_THAN:b=a<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:b=a>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:b=a<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:b=
1994 a>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:b=a>=this.lowerBoundary&&a<=this.upperBoundary;break;case OpenLayers.Filter.Comparison.LIKE:b=RegExp(this.value,"gi").test(a);break;case OpenLayers.Filter.Comparison.IS_NULL:b=null===a}return b},value2regex:function(a,b,c){if("."==a)throw Error("'.' is an unsupported wildCard character for OpenLayers.Filter.Comparison");a=a?a:"*";b=b?b:".";this.value=this.value.replace(RegExp("\\"+(c?c:"!")+"(.|$)","g"),"\\$1");this.value=this.value.replace(RegExp("\\"+
1995 b,"g"),".");this.value=this.value.replace(RegExp("\\"+a,"g"),".*");this.value=this.value.replace(RegExp("\\\\.\\*","g"),"\\"+a);return this.value=this.value.replace(RegExp("\\\\\\.","g"),"\\"+b)},regex2value:function(){var a=this.value,a=a.replace(/!/g,"!!"),a=a.replace(/(\\)?\\\./g,function(a,c){return c?a:"!."}),a=a.replace(/(\\)?\\\*/g,function(a,c){return c?a:"!*"}),a=a.replace(/\\\\/g,"\\");return a=a.replace(/\.\*/g,"*")},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison,
1996 this)},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Filter.Comparison.IS_NULL="NULL";OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Filter.Function=OpenLayers.Class(OpenLayers.Filter,{name:null,params:null,CLASS_NAME:"OpenLayers.Filter.Function"});OpenLayers.Date={dateRegEx:/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))|Z)?$/,toISOString:function(){return"toISOString"in Date.prototype?function(a){return a.toISOString()}:function(a){return isNaN(a.getTime())?"Invalid Date":a.getUTCFullYear()+"-"+OpenLayers.Number.zeroPad(a.getUTCMonth()+1,2)+"-"+OpenLayers.Number.zeroPad(a.getUTCDate(),2)+"T"+OpenLayers.Number.zeroPad(a.getUTCHours(),2)+":"+OpenLayers.Number.zeroPad(a.getUTCMinutes(),
1997 2)+":"+OpenLayers.Number.zeroPad(a.getUTCSeconds(),2)+"."+OpenLayers.Number.zeroPad(a.getUTCMilliseconds(),3)+"Z"}}(),parse:function(a){var b;if((a=a.match(this.dateRegEx))&&(a[1]||a[7])){b=parseInt(a[1],10)||0;var c=parseInt(a[2],10)-1||0,d=parseInt(a[3],10)||1;b=new Date(Date.UTC(b,c,d));if(c=a[7]){var d=parseInt(a[4],10),e=parseInt(a[5],10),f=parseFloat(a[6]),g=f|0,f=Math.round(1E3*(f-g));b.setUTCHours(d,e,g,f);"Z"!==c&&(c=parseInt(c,10),a=parseInt(a[8],10)||0,a=-1E3*(60*60*c+60*a),b=new Date(b.getTime()+
1998 a))}}else b=new Date("invalid");return b}};OpenLayers.Format.Filter.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"ogc",schemaLocation:null,initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){var b={};this.readers.ogc.Filter.apply(this,[a,b]);return b.filter},readers:{ogc:{_expression:function(a){for(var b="",c=a.firstChild;c;c=
1999 c.nextSibling)switch(c.nodeType){case 1:a=this.readNode(c);a.property?b+="${"+a.property+"}":void 0!==a.value&&(b+=a.value);break;case 3:case 4:b+=c.nodeValue}return b},Filter:function(a,b){var c={fids:[],filters:[]};this.readChildNodes(a,c);0<c.fids.length?b.filter=new OpenLayers.Filter.FeatureId({fids:c.fids}):0<c.filters.length&&(b.filter=c.filters[0])},FeatureId:function(a,b){var c=a.getAttribute("fid");c&&b.fids.push(c)},And:function(a,b){var c=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND});
2000 this.readChildNodes(a,c);b.filters.push(c)},Or:function(a,b){var c=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.OR});this.readChildNodes(a,c);b.filters.push(c)},Not:function(a,b){var c=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.NOT});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsLessThan:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsGreaterThan:function(a,
2001 b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsLessThanOrEqualTo:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsGreaterThanOrEqualTo:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO});this.readChildNodes(a,c);b.filters.push(c)},
2002 PropertyIsBetween:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.BETWEEN});this.readChildNodes(a,c);b.filters.push(c)},Literal:function(a,b){b.value=OpenLayers.String.numericIf(this.getChildValue(a),!0)},PropertyName:function(a,b){b.property=this.getChildValue(a)},LowerBoundary:function(a,b){b.lowerBoundary=OpenLayers.String.numericIf(this.readers.ogc._expression.call(this,a),!0)},UpperBoundary:function(a,b){b.upperBoundary=OpenLayers.String.numericIf(this.readers.ogc._expression.call(this,
2003 a),!0)},Intersects:function(a,b){this.readSpatial(a,b,OpenLayers.Filter.Spatial.INTERSECTS)},Within:function(a,b){this.readSpatial(a,b,OpenLayers.Filter.Spatial.WITHIN)},Contains:function(a,b){this.readSpatial(a,b,OpenLayers.Filter.Spatial.CONTAINS)},DWithin:function(a,b){this.readSpatial(a,b,OpenLayers.Filter.Spatial.DWITHIN)},Distance:function(a,b){b.distance=parseInt(this.getChildValue(a));b.distanceUnits=a.getAttribute("units")},Function:function(a,b){},PropertyIsNull:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.IS_NULL});
2004 this.readChildNodes(a,c);b.filters.push(c)}}},readSpatial:function(a,b,c){c=new OpenLayers.Filter.Spatial({type:c});this.readChildNodes(a,c);c.value=c.components[0];delete c.components;b.filters.push(c)},encodeLiteral:function(a){a instanceof Date&&(a=OpenLayers.Date.toISOString(a));return a},writeOgcExpression:function(a,b){a instanceof OpenLayers.Filter.Function?this.writeNode("Function",a,b):this.writeNode("Literal",a,b);return b},write:function(a){return this.writers.ogc.Filter.apply(this,[a])},
2005 writers:{ogc:{Filter:function(a){var b=this.createElementNSPlus("ogc:Filter");this.writeNode(this.getFilterType(a),a,b);return b},_featureIds:function(a){for(var b=this.createDocumentFragment(),c=0,d=a.fids.length;c<d;++c)this.writeNode("ogc:FeatureId",a.fids[c],b);return b},FeatureId:function(a){return this.createElementNSPlus("ogc:FeatureId",{attributes:{fid:a}})},And:function(a){for(var b=this.createElementNSPlus("ogc:And"),c,d=0,e=a.filters.length;d<e;++d)c=a.filters[d],this.writeNode(this.getFilterType(c),
2006 c,b);return b},Or:function(a){for(var b=this.createElementNSPlus("ogc:Or"),c,d=0,e=a.filters.length;d<e;++d)c=a.filters[d],this.writeNode(this.getFilterType(c),c,b);return b},Not:function(a){var b=this.createElementNSPlus("ogc:Not");a=a.filters[0];this.writeNode(this.getFilterType(a),a,b);return b},PropertyIsLessThan:function(a){var b=this.createElementNSPlus("ogc:PropertyIsLessThan");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsGreaterThan:function(a){var b=
2007 this.createElementNSPlus("ogc:PropertyIsGreaterThan");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsLessThanOrEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsGreaterThanOrEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);
2008 return b},PropertyIsBetween:function(a){var b=this.createElementNSPlus("ogc:PropertyIsBetween");this.writeNode("PropertyName",a,b);this.writeNode("LowerBoundary",a,b);this.writeNode("UpperBoundary",a,b);return b},PropertyName:function(a){return this.createElementNSPlus("ogc:PropertyName",{value:a.property})},Literal:function(a){return this.createElementNSPlus("ogc:Literal",{value:(this.encodeLiteral||OpenLayers.Format.Filter.v1.prototype.encodeLiteral)(a)})},LowerBoundary:function(a){var b=this.createElementNSPlus("ogc:LowerBoundary");
2009 this.writeOgcExpression(a.lowerBoundary,b);return b},UpperBoundary:function(a){var b=this.createElementNSPlus("ogc:UpperBoundary");this.writeNode("Literal",a.upperBoundary,b);return b},INTERSECTS:function(a){return this.writeSpatial(a,"Intersects")},WITHIN:function(a){return this.writeSpatial(a,"Within")},CONTAINS:function(a){return this.writeSpatial(a,"Contains")},DWITHIN:function(a){var b=this.writeSpatial(a,"DWithin");this.writeNode("Distance",a,b);return b},Distance:function(a){return this.createElementNSPlus("ogc:Distance",
2010 {attributes:{units:a.distanceUnits},value:a.distance})},Function:function(a){var b=this.createElementNSPlus("ogc:Function",{attributes:{name:a.name}});a=a.params;for(var c=0,d=a.length;c<d;c++)this.writeOgcExpression(a[c],b);return b},PropertyIsNull:function(a){var b=this.createElementNSPlus("ogc:PropertyIsNull");this.writeNode("PropertyName",a,b);return b}}},getFilterType:function(a){var b=this.filterMap[a.type];if(!b)throw"Filter writing not supported for rule type: "+a.type;return b},filterMap:{"&&":"And",
2011 "||":"Or","!":"Not","==":"PropertyIsEqualTo","!=":"PropertyIsNotEqualTo","<":"PropertyIsLessThan",">":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike",NULL:"PropertyIsNull",BBOX:"BBOX",DWITHIN:"DWITHIN",WITHIN:"WITHIN",CONTAINS:"CONTAINS",INTERSECTS:"INTERSECTS",FID:"_featureIds"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){this.bounds=this.id=null},clone:function(){return new OpenLayers.Geometry},setBounds:function(a){a&&(this.bounds=a.clone())},clearBounds:function(){this.bounds=null;this.parent&&this.parent.clearBounds()},extendBounds:function(a){this.getBounds()?this.bounds.extend(a):this.setBounds(a)},getBounds:function(){null==this.bounds&&this.calculateBounds();
2012 return this.bounds},calculateBounds:function(){},distanceTo:function(a,b){},getVertices:function(a){},atPoint:function(a,b,c){var d=!1;null!=this.getBounds()&&null!=a&&(b=null!=b?b:0,c=null!=c?c:0,d=(new OpenLayers.Bounds(this.bounds.left-b,this.bounds.bottom-c,this.bounds.right+b,this.bounds.top+c)).containsLonLat(a));return d},getLength:function(){return 0},getArea:function(){return 0},getCentroid:function(){return null},toString:function(){return OpenLayers.Format&&OpenLayers.Format.WKT?OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this)):
2013 Object.prototype.toString.call(this)},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(a){var b;if(OpenLayers.Format&&OpenLayers.Format.WKT){var c=OpenLayers.Geometry.fromWKT.format;c||(c=new OpenLayers.Format.WKT,OpenLayers.Geometry.fromWKT.format=c);a=c.read(a);if(a instanceof OpenLayers.Feature.Vector)b=a.geometry;else if(OpenLayers.Util.isArray(a)){b=a.length;for(var c=Array(b),d=0;d<b;++d)c[d]=a[d].geometry;b=new OpenLayers.Geometry.Collection(c)}}return b};
2014 OpenLayers.Geometry.segmentsIntersect=function(a,b,c){var d=c&&c.point;c=c&&c.tolerance;var e=!1,f=a.x1-b.x1,g=a.y1-b.y1,h=a.x2-a.x1,k=a.y2-a.y1,l=b.y2-b.y1,m=b.x2-b.x1,n=l*h-m*k,l=m*g-l*f,g=h*g-k*f;0==n?0==l&&0==g&&(e=!0):(f=l/n,n=g/n,0<=f&&(1>=f&&0<=n&&1>=n)&&(d?(h=a.x1+f*h,n=a.y1+f*k,e=new OpenLayers.Geometry.Point(h,n)):e=!0));if(c)if(e){if(d)a:for(a=[a,b],b=0;2>b;++b)for(f=a[b],k=1;3>k;++k)if(h=f["x"+k],n=f["y"+k],d=Math.sqrt(Math.pow(h-e.x,2)+Math.pow(n-e.y,2)),d<c){e.x=h;e.y=n;break a}}else a:for(a=
2015 [a,b],b=0;2>b;++b)for(h=a[b],n=a[(b+1)%2],k=1;3>k;++k)if(f={x:h["x"+k],y:h["y"+k]},g=OpenLayers.Geometry.distanceToSegment(f,n),g.distance<c){e=d?new OpenLayers.Geometry.Point(f.x,f.y):!0;break a}return e};OpenLayers.Geometry.distanceToSegment=function(a,b){var c=OpenLayers.Geometry.distanceSquaredToSegment(a,b);c.distance=Math.sqrt(c.distance);return c};
2016 OpenLayers.Geometry.distanceSquaredToSegment=function(a,b){var c=a.x,d=a.y,e=b.x1,f=b.y1,g=b.x2,h=b.y2,k=g-e,l=h-f,m=(k*(c-e)+l*(d-f))/(Math.pow(k,2)+Math.pow(l,2));0>=m||(1<=m?(e=g,f=h):(e+=m*k,f+=m*l));return{distance:Math.pow(e-c,2)+Math.pow(f-d,2),x:e,y:f,along:m}};OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(a,b){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(a);this.y=parseFloat(b)},clone:function(a){null==a&&(a=new OpenLayers.Geometry.Point(this.x,this.y));OpenLayers.Util.applyDefaults(a,this);return a},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y)},distanceTo:function(a,b){var c=!(b&&!1===b.edge)&&b&&b.details,d,e,f,g,h;a instanceof
2017 OpenLayers.Geometry.Point?(e=this.x,f=this.y,g=a.x,h=a.y,d=Math.sqrt(Math.pow(e-g,2)+Math.pow(f-h,2)),d=c?{x0:e,y0:f,x1:g,y1:h,distance:d}:d):(d=a.distanceTo(this,b),c&&(d={x0:d.x1,y0:d.y1,x1:d.x0,y1:d.y0,distance:d.distance}));return d},equals:function(a){var b=!1;null!=a&&(b=this.x==a.x&&this.y==a.y||isNaN(this.x)&&isNaN(this.y)&&isNaN(a.x)&&isNaN(a.y));return b},toShortString:function(){return this.x+", "+this.y},move:function(a,b){this.x+=a;this.y+=b;this.clearBounds()},rotate:function(a,b){a*=
2018 Math.PI/180;var c=this.distanceTo(b),d=a+Math.atan2(this.y-b.y,this.x-b.x);this.x=b.x+c*Math.cos(d);this.y=b.y+c*Math.sin(d);this.clearBounds()},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y)},resize:function(a,b,c){this.x=b.x+a*(void 0==c?1:c)*(this.x-b.x);this.y=b.y+a*(this.y-b.y);this.clearBounds();return this},intersects:function(a){var b=!1;return b="OpenLayers.Geometry.Point"==a.CLASS_NAME?this.equals(a):a.intersects(this)},transform:function(a,b){a&&b&&(OpenLayers.Projection.transform(this,
2019 a,b),this.bounds=null);return this},getVertices:function(a){return[this]},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(a){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];null!=a&&this.addComponents(a)},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments)},clone:function(){for(var a=eval("new "+this.CLASS_NAME+"()"),b=0,c=this.components.length;b<c;b++)a.addComponent(this.components[b].clone());
2020 OpenLayers.Util.applyDefaults(a,this);return a},getComponentsString:function(){for(var a=[],b=0,c=this.components.length;b<c;b++)a.push(this.components[b].toShortString());return a.join(",")},calculateBounds:function(){this.bounds=null;var a=new OpenLayers.Bounds,b=this.components;if(b)for(var c=0,d=b.length;c<d;c++)a.extend(b[c].getBounds());null!=a.left&&(null!=a.bottom&&null!=a.right&&null!=a.top)&&this.setBounds(a)},addComponents:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=0,c=a.length;b<
2021 c;b++)this.addComponent(a[b])},addComponent:function(a,b){var c=!1;if(a&&(null==this.componentTypes||-1<OpenLayers.Util.indexOf(this.componentTypes,a.CLASS_NAME))){if(null!=b&&b<this.components.length){var c=this.components.slice(0,b),d=this.components.slice(b,this.components.length);c.push(a);this.components=c.concat(d)}else this.components.push(a);a.parent=this;this.clearBounds();c=!0}return c},removeComponents:function(a){var b=!1;OpenLayers.Util.isArray(a)||(a=[a]);for(var c=a.length-1;0<=c;--c)b=
2022 this.removeComponent(a[c])||b;return b},removeComponent:function(a){OpenLayers.Util.removeItem(this.components,a);this.clearBounds();return!0},getLength:function(){for(var a=0,b=0,c=this.components.length;b<c;b++)a+=this.components[b].getLength();return a},getArea:function(){for(var a=0,b=0,c=this.components.length;b<c;b++)a+=this.components[b].getArea();return a},getGeodesicArea:function(a){for(var b=0,c=0,d=this.components.length;c<d;c++)b+=this.components[c].getGeodesicArea(a);return b},getCentroid:function(a){if(!a)return this.components.length&&
2023 this.components[0].getCentroid();a=this.components.length;if(!a)return!1;for(var b=[],c=[],d=0,e=Number.MAX_VALUE,f,g=0;g<a;++g){f=this.components[g];var h=f.getArea();f=f.getCentroid(!0);isNaN(h)||(isNaN(f.x)||isNaN(f.y))||(b.push(h),d+=h,e=h<e&&0<h?h:e,c.push(f))}a=b.length;if(0===d){for(g=0;g<a;++g)b[g]=1;d=b.length}else{for(g=0;g<a;++g)b[g]/=e;d/=e}for(var k=e=0,g=0;g<a;++g)f=c[g],h=b[g],e+=f.x*h,k+=f.y*h;return new OpenLayers.Geometry.Point(e/d,k/d)},getGeodesicLength:function(a){for(var b=0,
2024 c=0,d=this.components.length;c<d;c++)b+=this.components[c].getGeodesicLength(a);return b},move:function(a,b){for(var c=0,d=this.components.length;c<d;c++)this.components[c].move(a,b)},rotate:function(a,b){for(var c=0,d=this.components.length;c<d;++c)this.components[c].rotate(a,b)},resize:function(a,b,c){for(var d=0;d<this.components.length;++d)this.components[d].resize(a,b,c);return this},distanceTo:function(a,b){for(var c=!(b&&!1===b.edge)&&b&&b.details,d,e,f,g=Number.POSITIVE_INFINITY,h=0,k=this.components.length;h<
2025 k&&!(d=this.components[h].distanceTo(a,b),f=c?d.distance:d,f<g&&(g=f,e=d,0==g));++h);return e},equals:function(a){var b=!0;if(a&&a.CLASS_NAME&&this.CLASS_NAME==a.CLASS_NAME)if(OpenLayers.Util.isArray(a.components)&&a.components.length==this.components.length)for(var c=0,d=this.components.length;c<d;++c){if(!this.components[c].equals(a.components[c])){b=!1;break}}else b=!1;else b=!1;return b},transform:function(a,b){if(a&&b){for(var c=0,d=this.components.length;c<d;c++)this.components[c].transform(a,
2026 b);this.bounds=null}return this},intersects:function(a){for(var b=!1,c=0,d=this.components.length;c<d&&!(b=a.intersects(this.components[c]));++c);return b},getVertices:function(a){for(var b=[],c=0,d=this.components.length;c<d;++c)Array.prototype.push.apply(b,this.components[c].getVertices(a));return b},CLASS_NAME:"OpenLayers.Geometry.Collection"});OpenLayers.Geometry.MultiPoint=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Point"],addPoint:function(a,b){this.addComponent(a,b)},removePoint:function(a){this.removeComponent(a)},CLASS_NAME:"OpenLayers.Geometry.MultiPoint"});OpenLayers.Geometry.Curve=OpenLayers.Class(OpenLayers.Geometry.MultiPoint,{componentTypes:["OpenLayers.Geometry.Point"],getLength:function(){var a=0;if(this.components&&1<this.components.length)for(var b=1,c=this.components.length;b<c;b++)a+=this.components[b-1].distanceTo(this.components[b]);return a},getGeodesicLength:function(a){var b=this;if(a){var c=new OpenLayers.Projection("EPSG:4326");c.equals(a)||(b=this.clone().transform(a,c))}a=0;if(b.components&&1<b.components.length)for(var d,e=1,f=b.components.length;e<
2027 f;e++)c=b.components[e-1],d=b.components[e],a+=OpenLayers.Util.distVincenty({lon:c.x,lat:c.y},{lon:d.x,lat:d.y});return 1E3*a},CLASS_NAME:"OpenLayers.Geometry.Curve"});OpenLayers.Geometry.LineString=OpenLayers.Class(OpenLayers.Geometry.Curve,{removeComponent:function(a){var b=this.components&&2<this.components.length;b&&OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);return b},intersects:function(a){var b=!1,c=a.CLASS_NAME;if("OpenLayers.Geometry.LineString"==c||"OpenLayers.Geometry.LinearRing"==c||"OpenLayers.Geometry.Point"==c){var d=this.getSortedSegments();a="OpenLayers.Geometry.Point"==c?[{x1:a.x,y1:a.y,x2:a.x,y2:a.y}]:a.getSortedSegments();
2028 var e,f,g,h,k,l,m,n=0,p=d.length;a:for(;n<p;++n){c=d[n];e=c.x1;f=c.x2;g=c.y1;h=c.y2;var q=0,r=a.length;for(;q<r;++q){k=a[q];if(k.x1>f)break;if(!(k.x2<e||(l=k.y1,m=k.y2,Math.min(l,m)>Math.max(g,h)||Math.max(l,m)<Math.min(g,h)||!OpenLayers.Geometry.segmentsIntersect(c,k)))){b=!0;break a}}}}else b=a.intersects(this);return b},getSortedSegments:function(){for(var a=this.components.length-1,b=Array(a),c,d,e=0;e<a;++e)c=this.components[e],d=this.components[e+1],b[e]=c.x<d.x?{x1:c.x,y1:c.y,x2:d.x,y2:d.y}:
2029 {x1:d.x,y1:d.y,x2:c.x,y2:c.y};return b.sort(function(a,b){return a.x1-b.x1})},splitWithSegment:function(a,b){for(var c=!(b&&!1===b.edge),d=b&&b.tolerance,e=[],f=this.getVertices(),g=[],h=[],k=!1,l,m,n,p={point:!0,tolerance:d},q=null,r=0,s=f.length-2;r<=s;++r)if(d=f[r],g.push(d.clone()),l=f[r+1],m={x1:d.x,y1:d.y,x2:l.x,y2:l.y},m=OpenLayers.Geometry.segmentsIntersect(a,m,p),m instanceof OpenLayers.Geometry.Point&&((n=m.x===a.x1&&m.y===a.y1||m.x===a.x2&&m.y===a.y2||m.equals(d)||m.equals(l)?!0:!1)||c))m.equals(h[h.length-
2030 1])||h.push(m.clone()),0===r&&m.equals(d)||m.equals(l)||(k=!0,m.equals(d)||g.push(m),e.push(new OpenLayers.Geometry.LineString(g)),g=[m.clone()]);k&&(g.push(l.clone()),e.push(new OpenLayers.Geometry.LineString(g)));if(0<h.length)var t=a.x1<a.x2?1:-1,u=a.y1<a.y2?1:-1,q={lines:e,points:h.sort(function(a,b){return t*a.x-t*b.x||u*a.y-u*b.y})};return q},split:function(a,b){var c=null,d=b&&b.mutual,e,f,g,h;if(a instanceof OpenLayers.Geometry.LineString){var k=this.getVertices(),l,m,n,p,q,r=[];g=[];for(var s=
2031 0,t=k.length-2;s<=t;++s){l=k[s];m=k[s+1];n={x1:l.x,y1:l.y,x2:m.x,y2:m.y};h=h||[a];d&&r.push(l.clone());for(var u=0;u<h.length;++u)if(p=h[u].splitWithSegment(n,b))if(q=p.lines,0<q.length&&(q.unshift(u,1),Array.prototype.splice.apply(h,q),u+=q.length-2),d)for(var v=0,w=p.points.length;v<w;++v)q=p.points[v],q.equals(l)||(r.push(q),g.push(new OpenLayers.Geometry.LineString(r)),r=q.equals(m)?[]:[q.clone()])}d&&(0<g.length&&0<r.length)&&(r.push(m.clone()),g.push(new OpenLayers.Geometry.LineString(r)))}else c=
2032 a.splitWith(this,b);h&&1<h.length?f=!0:h=[];g&&1<g.length?e=!0:g=[];if(f||e)c=d?[g,h]:h;return c},splitWith:function(a,b){return a.split(this,b)},getVertices:function(a){return!0===a?[this.components[0],this.components[this.components.length-1]]:!1===a?this.components.slice(1,this.components.length-1):this.components.slice()},distanceTo:function(a,b){var c=!(b&&!1===b.edge)&&b&&b.details,d,e={},f=Number.POSITIVE_INFINITY;if(a instanceof OpenLayers.Geometry.Point){for(var g=this.getSortedSegments(),
2033 h=a.x,k=a.y,l,m=0,n=g.length;m<n;++m)if(l=g[m],d=OpenLayers.Geometry.distanceToSegment(a,l),d.distance<f){if(f=d.distance,e=d,0===f)break}else if(l.x2>h&&(k>l.y1&&k<l.y2||k<l.y1&&k>l.y2))break;e=c?{distance:e.distance,x0:e.x,y0:e.y,x1:h,y1:k}:e.distance}else if(a instanceof OpenLayers.Geometry.LineString){var g=this.getSortedSegments(),h=a.getSortedSegments(),p,q,r=h.length,s={point:!0},m=0,n=g.length;a:for(;m<n;++m){k=g[m];l=k.x1;q=k.y1;for(var t=0;t<r;++t)if(d=h[t],p=OpenLayers.Geometry.segmentsIntersect(k,
2034 d,s)){f=0;e={distance:0,x0:p.x,y0:p.y,x1:p.x,y1:p.y};break a}else d=OpenLayers.Geometry.distanceToSegment({x:l,y:q},d),d.distance<f&&(f=d.distance,e={distance:f,x0:l,y0:q,x1:d.x,y1:d.y})}c||(e=e.distance);0!==f&&k&&(d=a.distanceTo(new OpenLayers.Geometry.Point(k.x2,k.y2),b),m=c?d.distance:d,m<f&&(e=c?{distance:f,x0:d.x1,y0:d.y1,x1:d.x0,y1:d.y0}:m))}else e=a.distanceTo(this,b),c&&(e={distance:e.distance,x0:e.x1,y0:e.y1,x1:e.x0,y1:e.y0});return e},simplify:function(a){if(this&&null!==this){var b=this.getVertices();
2035 if(3>b.length)return this;var c=function(a,b,d,k){for(var l=0,m=0,n=b,p;n<d;n++){p=a[b];var q=a[d],r=a[n],r=Math.abs(0.5*(p.x*q.y+q.x*r.y+r.x*p.y-q.x*p.y-r.x*q.y-p.x*r.y));p=Math.sqrt(Math.pow(p.x-q.x,2)+Math.pow(p.y-q.y,2));p=2*(r/p);p>l&&(l=p,m=n)}l>k&&m!=b&&(e.push(m),c(a,b,m,k),c(a,m,d,k))},d=b.length-1,e=[];e.push(0);for(e.push(d);b[0].equals(b[d]);)d--,e.push(d);c(b,0,d,a);a=[];e.sort(function(a,b){return a-b});for(d=0;d<e.length;d++)a.push(b[e[d]]);return new OpenLayers.Geometry.LineString(a)}return this},
2036 CLASS_NAME:"OpenLayers.Geometry.LineString"});OpenLayers.Geometry.MultiLineString=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LineString"],split:function(a,b){for(var c=null,d=b&&b.mutual,e,f,g,h,k=[],l=[a],m=0,n=this.components.length;m<n;++m){f=this.components[m];g=!1;for(var p=0;p<l.length;++p)if(e=f.split(l[p],b)){if(d){g=e[0];for(var q=0,r=g.length;q<r;++q)0===q&&k.length?k[k.length-1].addComponent(g[q]):k.push(new OpenLayers.Geometry.MultiLineString([g[q]]));g=!0;e=e[1]}if(e.length){e.unshift(p,
2037 1);Array.prototype.splice.apply(l,e);break}}g||(k.length?k[k.length-1].addComponent(f.clone()):k=[new OpenLayers.Geometry.MultiLineString(f.clone())])}k&&1<k.length?g=!0:k=[];l&&1<l.length?h=!0:l=[];if(g||h)c=d?[k,l]:l;return c},splitWith:function(a,b){var c=null,d=b&&b.mutual,e,f,g,h,k,l;if(a instanceof OpenLayers.Geometry.LineString){l=[];k=[a];for(var m=0,n=this.components.length;m<n;++m){g=!1;f=this.components[m];for(var p=0;p<k.length;++p)if(e=k[p].split(f,b)){d&&(g=e[0],g.length&&(g.unshift(p,
2038 1),Array.prototype.splice.apply(k,g),p+=g.length-2),e=e[1],0===e.length&&(e=[f.clone()]));g=0;for(var q=e.length;g<q;++g)0===g&&l.length?l[l.length-1].addComponent(e[g]):l.push(new OpenLayers.Geometry.MultiLineString([e[g]]));g=!0}g||(l.length?l[l.length-1].addComponent(f.clone()):l=[new OpenLayers.Geometry.MultiLineString([f.clone()])])}}else c=a.split(this);k&&1<k.length?h=!0:k=[];l&&1<l.length?g=!0:l=[];if(h||g)c=d?[k,l]:l;return c},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],addComponent:function(a,b){var c=!1,d=this.components.pop();null==b&&a.equals(d)||(c=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments));OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[this.components[0]]);return c},removeComponent:function(a){var b=this.components&&3<this.components.length;b&&(this.components.pop(),OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,
2039 arguments),OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[this.components[0]]));return b},move:function(a,b){for(var c=0,d=this.components.length;c<d-1;c++)this.components[c].move(a,b)},rotate:function(a,b){for(var c=0,d=this.components.length;c<d-1;++c)this.components[c].rotate(a,b)},resize:function(a,b,c){for(var d=0,e=this.components.length;d<e-1;++d)this.components[d].resize(a,b,c);return this},transform:function(a,b){if(a&&b){for(var c=0,d=this.components.length;c<d-1;c++)this.components[c].transform(a,
2040 b);this.bounds=null}return this},getCentroid:function(){if(this.components){var a=this.components.length;if(0<a&&2>=a)return this.components[0].clone();if(2<a){var b=0,c=0,d=this.components[0].x,e=this.components[0].y,f=-1*this.getArea();if(0!=f){for(var g=0;g<a-1;g++)var h=this.components[g],k=this.components[g+1],b=b+(h.x+k.x-2*d)*((h.x-d)*(k.y-e)-(k.x-d)*(h.y-e)),c=c+(h.y+k.y-2*e)*((h.x-d)*(k.y-e)-(k.x-d)*(h.y-e));b=d+b/(6*f);a=e+c/(6*f)}else{for(g=0;g<a-1;g++)b+=this.components[g].x,c+=this.components[g].y;
2041 b/=a-1;a=c/(a-1)}return new OpenLayers.Geometry.Point(b,a)}return null}},getArea:function(){var a=0;if(this.components&&2<this.components.length){for(var b=a=0,c=this.components.length;b<c-1;b++)var d=this.components[b],e=this.components[b+1],a=a+(d.x+e.x)*(e.y-d.y);a=-a/2}return a},getGeodesicArea:function(a){var b=this;if(a){var c=new OpenLayers.Projection("EPSG:4326");c.equals(a)||(b=this.clone().transform(a,c))}a=0;c=b.components&&b.components.length;if(2<c){for(var d,e,f=0;f<c-1;f++)d=b.components[f],
2042 e=b.components[f+1],a+=OpenLayers.Util.rad(e.x-d.x)*(2+Math.sin(OpenLayers.Util.rad(d.y))+Math.sin(OpenLayers.Util.rad(e.y)));a=40680631590769*a/2}return a},containsPoint:function(a){var b=OpenLayers.Number.limitSigDigs,c=b(a.x,14);a=b(a.y,14);for(var d=this.components.length-1,e,f,g,h,k,l=0,m=0;m<d;++m)if(e=this.components[m],g=b(e.x,14),e=b(e.y,14),f=this.components[m+1],h=b(f.x,14),f=b(f.y,14),e==f){if(a==e&&(g<=h&&c>=g&&c<=h||g>=h&&c<=g&&c>=h)){l=-1;break}}else{k=b((a-f)*((h-g)/(f-e))+h,14);if(k==
2043 c&&(e<f&&a>=e&&a<=f||e>f&&a<=e&&a>=f)){l=-1;break}k<=c||g!=h&&(k<Math.min(g,h)||k>Math.max(g,h))||(e<f&&a>=e&&a<f||e>f&&a<e&&a>=f)&&++l}return-1==l?1:!!(l&1)},intersects:function(a){var b=!1;if("OpenLayers.Geometry.Point"==a.CLASS_NAME)b=this.containsPoint(a);else if("OpenLayers.Geometry.LineString"==a.CLASS_NAME)b=a.intersects(this);else if("OpenLayers.Geometry.LinearRing"==a.CLASS_NAME)b=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[a]);else for(var c=0,d=a.components.length;c<
2044 d&&!(b=a.components[c].intersects(this));++c);return b},getVertices:function(a){return!0===a?[]:this.components.slice(0,this.components.length-1)},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],getArea:function(){var a=0;if(this.components&&0<this.components.length)for(var a=a+Math.abs(this.components[0].getArea()),b=1,c=this.components.length;b<c;b++)a-=Math.abs(this.components[b].getArea());return a},getGeodesicArea:function(a){var b=0;if(this.components&&0<this.components.length)for(var b=b+Math.abs(this.components[0].getGeodesicArea(a)),c=1,d=this.components.length;c<
2045 d;c++)b-=Math.abs(this.components[c].getGeodesicArea(a));return b},containsPoint:function(a){var b=this.components.length,c=!1;if(0<b&&(c=this.components[0].containsPoint(a),1!==c&&c&&1<b))for(var d,e=1;e<b;++e)if(d=this.components[e].containsPoint(a)){c=1===d?1:!1;break}return c},intersects:function(a){var b=!1,c,d;if("OpenLayers.Geometry.Point"==a.CLASS_NAME)b=this.containsPoint(a);else if("OpenLayers.Geometry.LineString"==a.CLASS_NAME||"OpenLayers.Geometry.LinearRing"==a.CLASS_NAME){c=0;for(d=
2046 this.components.length;c<d&&!(b=a.intersects(this.components[c]));++c);if(!b)for(c=0,d=a.components.length;c<d&&!(b=this.containsPoint(a.components[c]));++c);}else for(c=0,d=a.components.length;c<d&&!(b=this.intersects(a.components[c]));++c);if(!b&&"OpenLayers.Geometry.Polygon"==a.CLASS_NAME){var e=this.components[0];c=0;for(d=e.components.length;c<d&&!(b=a.containsPoint(e.components[c]));++c);}return b},distanceTo:function(a,b){return b&&!1===b.edge&&this.intersects(a)?0:OpenLayers.Geometry.Collection.prototype.distanceTo.apply(this,
2047 [a,b])},CLASS_NAME:"OpenLayers.Geometry.Polygon"});OpenLayers.Geometry.Polygon.createRegularPolygon=function(a,b,c,d){var e=Math.PI*(1/c-0.5);d&&(e+=d/180*Math.PI);for(var f,g=[],h=0;h<c;++h)f=e+2*h*Math.PI/c,d=a.x+b*Math.cos(f),f=a.y+b*Math.sin(f),g.push(new OpenLayers.Geometry.Point(d,f));a=new OpenLayers.Geometry.LinearRing(g);return new OpenLayers.Geometry.Polygon([a])};OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Format.GML=OpenLayers.Class(OpenLayers.Format.XML,{featureNS:"http://mapserver.gis.umn.edu/mapserver",featurePrefix:"feature",featureName:"featureMember",layerName:"features",geometryName:"geometry",collectionName:"FeatureCollection",gmlns:"http://www.opengis.net/gml",extractAttributes:!0,xy:!0,initialize:function(a){this.regExes={trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g};OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){"string"==
2048 typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a=this.getElementsByTagNameNS(a.documentElement,this.gmlns,this.featureName);for(var b=[],c=0;c<a.length;c++){var d=this.parseFeature(a[c]);d&&b.push(d)}return b},parseFeature:function(a){for(var b="MultiPolygon Polygon MultiLineString LineString MultiPoint Point Envelope".split(" "),c,d,e,f=0;f<b.length;++f)if(c=b[f],d=this.getElementsByTagNameNS(a,this.gmlns,c),0<d.length){if(e=this.parseGeometry[c.toLowerCase()])e=e.apply(this,
2049 [d[0]]),this.internalProjection&&this.externalProjection&&e.transform(this.externalProjection,this.internalProjection);else throw new TypeError("Unsupported geometry type: "+c);break}var g;c=this.getElementsByTagNameNS(a,this.gmlns,"Box");for(f=0;f<c.length;++f)b=c[f],d=this.parseGeometry.box.apply(this,[b]),b=b.parentNode,"boundedBy"===(b.localName||b.nodeName.split(":").pop())?g=d:e=d.toGeometry();var h;this.extractAttributes&&(h=this.parseAttributes(a));h=new OpenLayers.Feature.Vector(e,h);h.bounds=
2050 g;h.gml={featureType:a.firstChild.nodeName.split(":")[1],featureNS:a.firstChild.namespaceURI,featureNSPrefix:a.firstChild.prefix};a=a.firstChild;for(var k;a&&(1!=a.nodeType||!(k=a.getAttribute("fid")||a.getAttribute("id")));)a=a.nextSibling;h.fid=k;return h},parseGeometry:{point:function(a){var b,c;c=[];b=this.getElementsByTagNameNS(a,this.gmlns,"pos");0<b.length&&(c=b[0].firstChild.nodeValue,c=c.replace(this.regExes.trimSpace,""),c=c.split(this.regExes.splitSpace));0==c.length&&(b=this.getElementsByTagNameNS(a,
2051 this.gmlns,"coordinates"),0<b.length&&(c=b[0].firstChild.nodeValue,c=c.replace(this.regExes.removeSpace,""),c=c.split(",")));0==c.length&&(b=this.getElementsByTagNameNS(a,this.gmlns,"coord"),0<b.length&&(a=this.getElementsByTagNameNS(b[0],this.gmlns,"X"),b=this.getElementsByTagNameNS(b[0],this.gmlns,"Y"),0<a.length&&0<b.length&&(c=[a[0].firstChild.nodeValue,b[0].firstChild.nodeValue])));2==c.length&&(c[2]=null);return this.xy?new OpenLayers.Geometry.Point(c[0],c[1],c[2]):new OpenLayers.Geometry.Point(c[1],
2052 c[0],c[2])},multipoint:function(a){a=this.getElementsByTagNameNS(a,this.gmlns,"Point");var b=[];if(0<a.length)for(var c,d=0;d<a.length;++d)(c=this.parseGeometry.point.apply(this,[a[d]]))&&b.push(c);return new OpenLayers.Geometry.MultiPoint(b)},linestring:function(a,b){var c,d;d=[];var e=[];c=this.getElementsByTagNameNS(a,this.gmlns,"posList");if(0<c.length){d=this.getChildValue(c[0]);d=d.replace(this.regExes.trimSpace,"");d=d.split(this.regExes.splitSpace);var f=parseInt(c[0].getAttribute("dimension")),
2053 g,h,k;for(c=0;c<d.length/f;++c)g=c*f,h=d[g],k=d[g+1],g=2==f?null:d[g+2],this.xy?e.push(new OpenLayers.Geometry.Point(h,k,g)):e.push(new OpenLayers.Geometry.Point(k,h,g))}if(0==d.length&&(c=this.getElementsByTagNameNS(a,this.gmlns,"coordinates"),0<c.length))for(d=this.getChildValue(c[0]),d=d.replace(this.regExes.trimSpace,""),d=d.replace(this.regExes.trimComma,","),f=d.split(this.regExes.splitSpace),c=0;c<f.length;++c)d=f[c].split(","),2==d.length&&(d[2]=null),this.xy?e.push(new OpenLayers.Geometry.Point(d[0],
2054 d[1],d[2])):e.push(new OpenLayers.Geometry.Point(d[1],d[0],d[2]));d=null;0!=e.length&&(d=b?new OpenLayers.Geometry.LinearRing(e):new OpenLayers.Geometry.LineString(e));return d},multilinestring:function(a){a=this.getElementsByTagNameNS(a,this.gmlns,"LineString");var b=[];if(0<a.length)for(var c,d=0;d<a.length;++d)(c=this.parseGeometry.linestring.apply(this,[a[d]]))&&b.push(c);return new OpenLayers.Geometry.MultiLineString(b)},polygon:function(a){a=this.getElementsByTagNameNS(a,this.gmlns,"LinearRing");
2055 var b=[];if(0<a.length)for(var c,d=0;d<a.length;++d)(c=this.parseGeometry.linestring.apply(this,[a[d],!0]))&&b.push(c);return new OpenLayers.Geometry.Polygon(b)},multipolygon:function(a){a=this.getElementsByTagNameNS(a,this.gmlns,"Polygon");var b=[];if(0<a.length)for(var c,d=0;d<a.length;++d)(c=this.parseGeometry.polygon.apply(this,[a[d]]))&&b.push(c);return new OpenLayers.Geometry.MultiPolygon(b)},envelope:function(a){var b=[],c,d,e=this.getElementsByTagNameNS(a,this.gmlns,"lowerCorner");if(0<e.length){c=
2056 [];0<e.length&&(c=e[0].firstChild.nodeValue,c=c.replace(this.regExes.trimSpace,""),c=c.split(this.regExes.splitSpace));2==c.length&&(c[2]=null);var f=this.xy?new OpenLayers.Geometry.Point(c[0],c[1],c[2]):new OpenLayers.Geometry.Point(c[1],c[0],c[2])}a=this.getElementsByTagNameNS(a,this.gmlns,"upperCorner");if(0<a.length){c=[];0<a.length&&(c=a[0].firstChild.nodeValue,c=c.replace(this.regExes.trimSpace,""),c=c.split(this.regExes.splitSpace));2==c.length&&(c[2]=null);var g=this.xy?new OpenLayers.Geometry.Point(c[0],
2057 c[1],c[2]):new OpenLayers.Geometry.Point(c[1],c[0],c[2])}f&&g&&(b.push(new OpenLayers.Geometry.Point(f.x,f.y)),b.push(new OpenLayers.Geometry.Point(g.x,f.y)),b.push(new OpenLayers.Geometry.Point(g.x,g.y)),b.push(new OpenLayers.Geometry.Point(f.x,g.y)),b.push(new OpenLayers.Geometry.Point(f.x,f.y)),b=new OpenLayers.Geometry.LinearRing(b),d=new OpenLayers.Geometry.Polygon([b]));return d},box:function(a){var b=this.getElementsByTagNameNS(a,this.gmlns,"coordinates"),c=a=null;0<b.length&&(b=b[0].firstChild.nodeValue,
2058 b=b.split(" "),2==b.length&&(a=b[0].split(","),c=b[1].split(",")));if(null!==a&&null!==c)return new OpenLayers.Bounds(parseFloat(a[0]),parseFloat(a[1]),parseFloat(c[0]),parseFloat(c[1]))}},parseAttributes:function(a){var b={};a=a.firstChild;for(var c,d,e;a;){if(1==a.nodeType){a=a.childNodes;for(c=0;c<a.length;++c)if(d=a[c],1==d.nodeType)if(e=d.childNodes,1==e.length){if(e=e[0],3==e.nodeType||4==e.nodeType)d=d.prefix?d.nodeName.split(":")[1]:d.nodeName,e=e.nodeValue.replace(this.regExes.trimSpace,
2059 ""),b[d]=e}else b[d.nodeName.split(":").pop()]=null;break}a=a.nextSibling}return b},write:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=this.createElementNS("http://www.opengis.net/wfs","wfs:"+this.collectionName),c=0;c<a.length;c++)b.appendChild(this.createFeatureXML(a[c]));return OpenLayers.Format.XML.prototype.write.apply(this,[b])},createFeatureXML:function(a){var b=this.buildGeometryNode(a.geometry),c=this.createElementNS(this.featureNS,this.featurePrefix+":"+this.geometryName);c.appendChild(b);
2060 var b=this.createElementNS(this.gmlns,"gml:"+this.featureName),d=this.createElementNS(this.featureNS,this.featurePrefix+":"+this.layerName);d.setAttribute("fid",a.fid||a.id);d.appendChild(c);for(var e in a.attributes){var c=this.createTextNode(a.attributes[e]),f=e.substring(e.lastIndexOf(":")+1),f=this.createElementNS(this.featureNS,this.featurePrefix+":"+f);f.appendChild(c);d.appendChild(f)}b.appendChild(d);return b},buildGeometryNode:function(a){this.externalProjection&&this.internalProjection&&
2061 (a=a.clone(),a.transform(this.internalProjection,this.externalProjection));var b=a.CLASS_NAME,b=b.substring(b.lastIndexOf(".")+1);return this.buildGeometry[b.toLowerCase()].apply(this,[a])},buildGeometry:{point:function(a){var b=this.createElementNS(this.gmlns,"gml:Point");b.appendChild(this.buildCoordinatesNode(a));return b},multipoint:function(a){var b=this.createElementNS(this.gmlns,"gml:MultiPoint");a=a.components;for(var c,d,e=0;e<a.length;e++)c=this.createElementNS(this.gmlns,"gml:pointMember"),
2062 d=this.buildGeometry.point.apply(this,[a[e]]),c.appendChild(d),b.appendChild(c);return b},linestring:function(a){var b=this.createElementNS(this.gmlns,"gml:LineString");b.appendChild(this.buildCoordinatesNode(a));return b},multilinestring:function(a){var b=this.createElementNS(this.gmlns,"gml:MultiLineString");a=a.components;for(var c,d,e=0;e<a.length;++e)c=this.createElementNS(this.gmlns,"gml:lineStringMember"),d=this.buildGeometry.linestring.apply(this,[a[e]]),c.appendChild(d),b.appendChild(c);
2063 return b},linearring:function(a){var b=this.createElementNS(this.gmlns,"gml:LinearRing");b.appendChild(this.buildCoordinatesNode(a));return b},polygon:function(a){var b=this.createElementNS(this.gmlns,"gml:Polygon");a=a.components;for(var c,d,e=0;e<a.length;++e)c=0==e?"outerBoundaryIs":"innerBoundaryIs",c=this.createElementNS(this.gmlns,"gml:"+c),d=this.buildGeometry.linearring.apply(this,[a[e]]),c.appendChild(d),b.appendChild(c);return b},multipolygon:function(a){var b=this.createElementNS(this.gmlns,
2064 "gml:MultiPolygon");a=a.components;for(var c,d,e=0;e<a.length;++e)c=this.createElementNS(this.gmlns,"gml:polygonMember"),d=this.buildGeometry.polygon.apply(this,[a[e]]),c.appendChild(d),b.appendChild(c);return b},bounds:function(a){var b=this.createElementNS(this.gmlns,"gml:Box");b.appendChild(this.buildCoordinatesNode(a));return b}},buildCoordinatesNode:function(a){var b=this.createElementNS(this.gmlns,"gml:coordinates");b.setAttribute("decimal",".");b.setAttribute("cs",",");b.setAttribute("ts",
2065 " ");var c=[];if(a instanceof OpenLayers.Bounds)c.push(a.left+","+a.bottom),c.push(a.right+","+a.top);else{a=a.components?a.components:[a];for(var d=0;d<a.length;d++)c.push(a[d].x+","+a[d].y)}c=this.createTextNode(c.join(" "));b.appendChild(c);return b},CLASS_NAME:"OpenLayers.Format.GML"});OpenLayers.Format.GML||(OpenLayers.Format.GML={});
2066 OpenLayers.Format.GML.Base=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs"},defaultPrefix:"gml",schemaLocation:null,featureType:null,featureNS:null,geometryName:"geometry",extractAttributes:!0,srsName:null,xy:!0,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g,featureMember:/^(.*:)?featureMembers?$/},
2067 initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a]);this.setGeometryTypes();a&&a.featureNS&&this.setNamespace("feature",a.featureNS);this.singleFeatureType=!a||"string"===typeof a.featureType},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b=[];this.readNode(a,{features:b},!0);if(0==b.length){var c=this.getElementsByTagNameNS(a,this.namespaces.gml,"featureMember");if(c.length){a=
2068 0;for(var d=c.length;a<d;++a)this.readNode(c[a],{features:b},!0)}else c=this.getElementsByTagNameNS(a,this.namespaces.gml,"featureMembers"),c.length&&this.readNode(c[0],{features:b},!0)}return b},readNode:function(a,b,c){!0===c&&!0===this.autoConfig&&(this.featureType=null,delete this.namespaceAlias[this.featureNS],delete this.namespaces.feature,this.featureNS=null);this.featureNS||(a.prefix in this.namespaces||a.parentNode.namespaceURI!=this.namespaces.gml||!this.regExes.featureMember.test(a.parentNode.nodeName))||
2069 (this.featureType=a.nodeName.split(":").pop(),this.setNamespace("feature",a.namespaceURI),this.featureNS=a.namespaceURI,this.autoConfig=!0);return OpenLayers.Format.XML.prototype.readNode.apply(this,[a,b])},readers:{gml:{_inherit:function(a,b,c){},featureMember:function(a,b){this.readChildNodes(a,b)},featureMembers:function(a,b){this.readChildNodes(a,b)},name:function(a,b){b.name=this.getChildValue(a)},boundedBy:function(a,b){var c={};this.readChildNodes(a,c);c.components&&0<c.components.length&&
2070 (b.bounds=c.components[0])},Point:function(a,b){var c={points:[]};this.readChildNodes(a,c);b.components||(b.components=[]);b.components.push(c.points[0])},coordinates:function(a,b){for(var c=this.getChildValue(a).replace(this.regExes.trimSpace,""),c=c.replace(this.regExes.trimComma,","),c=c.split(this.regExes.splitSpace),d,e=c.length,f=Array(e),g=0;g<e;++g)d=c[g].split(","),f[g]=this.xy?new OpenLayers.Geometry.Point(d[0],d[1],d[2]):new OpenLayers.Geometry.Point(d[1],d[0],d[2]);b.points=f},coord:function(a,
2071 b){var c={};this.readChildNodes(a,c);b.points||(b.points=[]);b.points.push(new OpenLayers.Geometry.Point(c.x,c.y,c.z))},X:function(a,b){b.x=this.getChildValue(a)},Y:function(a,b){b.y=this.getChildValue(a)},Z:function(a,b){b.z=this.getChildValue(a)},MultiPoint:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components=[new OpenLayers.Geometry.MultiPoint(c.components)]},pointMember:function(a,b){this.readChildNodes(a,b)},LineString:function(a,
2072 b){var c={};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components||(b.components=[]);b.components.push(new OpenLayers.Geometry.LineString(c.points))},MultiLineString:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components=[new OpenLayers.Geometry.MultiLineString(c.components)]},lineStringMember:function(a,b){this.readChildNodes(a,b)},Polygon:function(a,b){var c={outer:null,inner:[]};this.readers.gml._inherit.apply(this,
2073 [a,c,b]);this.readChildNodes(a,c);c.inner.unshift(c.outer);b.components||(b.components=[]);b.components.push(new OpenLayers.Geometry.Polygon(c.inner))},LinearRing:function(a,b){var c={};this.readers.gml._inherit.apply(this,[a,c]);this.readChildNodes(a,c);b.components=[new OpenLayers.Geometry.LinearRing(c.points)]},MultiPolygon:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components=[new OpenLayers.Geometry.MultiPolygon(c.components)]},
2074 polygonMember:function(a,b){this.readChildNodes(a,b)},GeometryCollection:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components=[new OpenLayers.Geometry.Collection(c.components)]},geometryMember:function(a,b){this.readChildNodes(a,b)}},feature:{"*":function(a,b){var c,d=a.localName||a.nodeName.split(":").pop();b.features?this.singleFeatureType||-1===OpenLayers.Util.indexOf(this.featureType,d)?d===this.featureType&&(c="_typeName"):c=
2075 "_typeName":0==a.childNodes.length||1==a.childNodes.length&&3==a.firstChild.nodeType?this.extractAttributes&&(c="_attribute"):c="_geometry";c&&this.readers.feature[c].apply(this,[a,b])},_typeName:function(a,b){var c={components:[],attributes:{}};this.readChildNodes(a,c);c.name&&(c.attributes.name=c.name);var d=new OpenLayers.Feature.Vector(c.components[0],c.attributes);this.singleFeatureType||(d.type=a.nodeName.split(":").pop(),d.namespace=a.namespaceURI);var e=a.getAttribute("fid")||this.getAttributeNS(a,
2076 this.namespaces.gml,"id");e&&(d.fid=e);this.internalProjection&&(this.externalProjection&&d.geometry)&&d.geometry.transform(this.externalProjection,this.internalProjection);c.bounds&&(d.bounds=c.bounds);b.features.push(d)},_geometry:function(a,b){this.geometryName||(this.geometryName=a.nodeName.split(":").pop());this.readChildNodes(a,b)},_attribute:function(a,b){var c=a.localName||a.nodeName.split(":").pop(),d=this.getChildValue(a);b.attributes[c]=d}},wfs:{FeatureCollection:function(a,b){this.readChildNodes(a,
2077 b)}}},write:function(a){var b;b=OpenLayers.Util.isArray(a)?"featureMembers":"featureMember";a=this.writeNode("gml:"+b,a);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},writers:{gml:{featureMember:function(a){var b=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",a,b);return b},MultiPoint:function(a){var b=this.createElementNSPlus("gml:MultiPoint");a=a.components||[a];
2078 for(var c=0,d=a.length;c<d;++c)this.writeNode("pointMember",a[c],b);return b},pointMember:function(a){var b=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",a,b);return b},MultiLineString:function(a){var b=this.createElementNSPlus("gml:MultiLineString");a=a.components||[a];for(var c=0,d=a.length;c<d;++c)this.writeNode("lineStringMember",a[c],b);return b},lineStringMember:function(a){var b=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",a,b);return b},
2079 MultiPolygon:function(a){var b=this.createElementNSPlus("gml:MultiPolygon");a=a.components||[a];for(var c=0,d=a.length;c<d;++c)this.writeNode("polygonMember",a[c],b);return b},polygonMember:function(a){var b=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",a,b);return b},GeometryCollection:function(a){for(var b=this.createElementNSPlus("gml:GeometryCollection"),c=0,d=a.components.length;c<d;++c)this.writeNode("geometryMember",a.components[c],b);return b},geometryMember:function(a){var b=
2080 this.createElementNSPlus("gml:geometryMember");a=this.writeNode("feature:_geometry",a);b.appendChild(a.firstChild);return b}},feature:{_typeName:function(a){var b=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:a.fid}});a.geometry&&this.writeNode("feature:_geometry",a.geometry,b);for(var c in a.attributes){var d=a.attributes[c];null!=d&&this.writeNode("feature:_attribute",{name:c,value:d},b)}return b},_geometry:function(a){this.externalProjection&&this.internalProjection&&(a=
2081 a.clone().transform(this.internalProjection,this.externalProjection));var b=this.createElementNSPlus("feature:"+this.geometryName);a=this.writeNode("gml:"+this.geometryTypes[a.CLASS_NAME],a,b);this.srsName&&a.setAttribute("srsName",this.srsName);return b},_attribute:function(a){return this.createElementNSPlus("feature:"+a.name,{value:a.value})}},wfs:{FeatureCollection:function(a){for(var b=this.createElementNSPlus("wfs:FeatureCollection"),c=0,d=a.length;c<d;++c)this.writeNode("gml:featureMember",
2082 a[c],b);return b}}},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":"LineString","OpenLayers.Geometry.MultiLineString":"MultiLineString","OpenLayers.Geometry.Polygon":"Polygon","OpenLayers.Geometry.MultiPolygon":"MultiPolygon","OpenLayers.Geometry.Collection":"GeometryCollection"}},CLASS_NAME:"OpenLayers.Format.GML.Base"});OpenLayers.Format.GML.v3=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",curve:!1,multiCurve:!0,surface:!1,multiSurface:!0,initialize:function(a){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[a])},readers:{gml:OpenLayers.Util.applyDefaults({_inherit:function(a,b,c){if(a=parseInt(a.getAttribute("srsDimension"),10)||c&&c.srsDimension)b.srsDimension=a},featureMembers:function(a,
2083 b){this.readChildNodes(a,b)},Curve:function(a,b){var c={points:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);b.components||(b.components=[]);b.components.push(new OpenLayers.Geometry.LineString(c.points))},segments:function(a,b){this.readChildNodes(a,b)},LineStringSegment:function(a,b){var c={};this.readChildNodes(a,c);c.points&&Array.prototype.push.apply(b.points,c.points)},pos:function(a,b){var c=this.getChildValue(a).replace(this.regExes.trimSpace,"").split(this.regExes.splitSpace),
2084 c=this.xy?new OpenLayers.Geometry.Point(c[0],c[1],c[2]):new OpenLayers.Geometry.Point(c[1],c[0],c[2]);b.points=[c]},posList:function(a,b){for(var c=this.getChildValue(a).replace(this.regExes.trimSpace,"").split(this.regExes.splitSpace),d=b.srsDimension||parseInt(a.getAttribute("srsDimension")||a.getAttribute("dimension"),10)||2,e,f,g,h=Array(c.length/d),k=0,l=c.length;k<l;k+=d)e=c[k],f=c[k+1],g=2==d?void 0:c[k+2],h[k/d]=this.xy?new OpenLayers.Geometry.Point(e,f,g):new OpenLayers.Geometry.Point(f,
2085 e,g);b.points=h},Surface:function(a,b){this.readChildNodes(a,b)},patches:function(a,b){this.readChildNodes(a,b)},PolygonPatch:function(a,b){this.readers.gml.Polygon.apply(this,[a,b])},exterior:function(a,b){var c={};this.readChildNodes(a,c);b.outer=c.components[0]},interior:function(a,b){var c={};this.readChildNodes(a,c);b.inner.push(c.components[0])},MultiCurve:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);0<c.components.length&&(b.components=
2086 [new OpenLayers.Geometry.MultiLineString(c.components)])},curveMember:function(a,b){this.readChildNodes(a,b)},MultiSurface:function(a,b){var c={components:[]};this.readers.gml._inherit.apply(this,[a,c,b]);this.readChildNodes(a,c);0<c.components.length&&(b.components=[new OpenLayers.Geometry.MultiPolygon(c.components)])},surfaceMember:function(a,b){this.readChildNodes(a,b)},surfaceMembers:function(a,b){this.readChildNodes(a,b)},pointMembers:function(a,b){this.readChildNodes(a,b)},lineStringMembers:function(a,
2087 b){this.readChildNodes(a,b)},polygonMembers:function(a,b){this.readChildNodes(a,b)},geometryMembers:function(a,b){this.readChildNodes(a,b)},Envelope:function(a,b){var c={points:Array(2)};this.readChildNodes(a,c);b.components||(b.components=[]);var d=c.points[0],c=c.points[1];b.components.push(new OpenLayers.Bounds(d.x,d.y,c.x,c.y))},lowerCorner:function(a,b){var c={};this.readers.gml.pos.apply(this,[a,c]);b.points[0]=c.points[0]},upperCorner:function(a,b){var c={};this.readers.gml.pos.apply(this,
2088 [a,c]);b.points[1]=c.points[0]}},OpenLayers.Format.GML.Base.prototype.readers.gml),feature:OpenLayers.Format.GML.Base.prototype.readers.feature,wfs:OpenLayers.Format.GML.Base.prototype.readers.wfs},write:function(a){var b;b=OpenLayers.Util.isArray(a)?"featureMembers":"featureMember";a=this.writeNode("gml:"+b,a);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},writers:{gml:OpenLayers.Util.applyDefaults({featureMembers:function(a){for(var b=
2089 this.createElementNSPlus("gml:featureMembers"),c=0,d=a.length;c<d;++c)this.writeNode("feature:_typeName",a[c],b);return b},Point:function(a){var b=this.createElementNSPlus("gml:Point");this.writeNode("pos",a,b);return b},pos:function(a){return this.createElementNSPlus("gml:pos",{value:this.xy?a.x+" "+a.y:a.y+" "+a.x})},LineString:function(a){var b=this.createElementNSPlus("gml:LineString");this.writeNode("posList",a.components,b);return b},Curve:function(a){var b=this.createElementNSPlus("gml:Curve");
2090 this.writeNode("segments",a,b);return b},segments:function(a){var b=this.createElementNSPlus("gml:segments");this.writeNode("LineStringSegment",a,b);return b},LineStringSegment:function(a){var b=this.createElementNSPlus("gml:LineStringSegment");this.writeNode("posList",a.components,b);return b},posList:function(a){for(var b=a.length,c=Array(b),d,e=0;e<b;++e)d=a[e],c[e]=this.xy?d.x+" "+d.y:d.y+" "+d.x;return this.createElementNSPlus("gml:posList",{value:c.join(" ")})},Surface:function(a){var b=this.createElementNSPlus("gml:Surface");
2091 this.writeNode("patches",a,b);return b},patches:function(a){var b=this.createElementNSPlus("gml:patches");this.writeNode("PolygonPatch",a,b);return b},PolygonPatch:function(a){var b=this.createElementNSPlus("gml:PolygonPatch",{attributes:{interpolation:"planar"}});this.writeNode("exterior",a.components[0],b);for(var c=1,d=a.components.length;c<d;++c)this.writeNode("interior",a.components[c],b);return b},Polygon:function(a){var b=this.createElementNSPlus("gml:Polygon");this.writeNode("exterior",a.components[0],
2092 b);for(var c=1,d=a.components.length;c<d;++c)this.writeNode("interior",a.components[c],b);return b},exterior:function(a){var b=this.createElementNSPlus("gml:exterior");this.writeNode("LinearRing",a,b);return b},interior:function(a){var b=this.createElementNSPlus("gml:interior");this.writeNode("LinearRing",a,b);return b},LinearRing:function(a){var b=this.createElementNSPlus("gml:LinearRing");this.writeNode("posList",a.components,b);return b},MultiCurve:function(a){var b=this.createElementNSPlus("gml:MultiCurve");
2093 a=a.components||[a];for(var c=0,d=a.length;c<d;++c)this.writeNode("curveMember",a[c],b);return b},curveMember:function(a){var b=this.createElementNSPlus("gml:curveMember");this.curve?this.writeNode("Curve",a,b):this.writeNode("LineString",a,b);return b},MultiSurface:function(a){var b=this.createElementNSPlus("gml:MultiSurface");a=a.components||[a];for(var c=0,d=a.length;c<d;++c)this.writeNode("surfaceMember",a[c],b);return b},surfaceMember:function(a){var b=this.createElementNSPlus("gml:surfaceMember");
2094 this.surface?this.writeNode("Surface",a,b):this.writeNode("Polygon",a,b);return b},Envelope:function(a){var b=this.createElementNSPlus("gml:Envelope");this.writeNode("lowerCorner",a,b);this.writeNode("upperCorner",a,b);this.srsName&&b.setAttribute("srsName",this.srsName);return b},lowerCorner:function(a){return this.createElementNSPlus("gml:lowerCorner",{value:this.xy?a.left+" "+a.bottom:a.bottom+" "+a.left})},upperCorner:function(a){return this.createElementNSPlus("gml:upperCorner",{value:this.xy?
2095 a.right+" "+a.top:a.top+" "+a.right})}},OpenLayers.Format.GML.Base.prototype.writers.gml),feature:OpenLayers.Format.GML.Base.prototype.writers.feature,wfs:OpenLayers.Format.GML.Base.prototype.writers.wfs},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":!0===this.curve?"Curve":"LineString","OpenLayers.Geometry.MultiLineString":!1===this.multiCurve?"MultiLineString":"MultiCurve","OpenLayers.Geometry.Polygon":!0===
2096 this.surface?"Surface":"Polygon","OpenLayers.Geometry.MultiPolygon":!1===this.multiSurface?"MultiPolygon":"MultiSurface","OpenLayers.Geometry.Collection":"GeometryCollection"}},CLASS_NAME:"OpenLayers.Format.GML.v3"});OpenLayers.Format.Filter.v1_1_0=OpenLayers.Class(OpenLayers.Format.GML.v3,OpenLayers.Format.Filter.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.1.0/filter.xsd",initialize:function(a){OpenLayers.Format.GML.v3.prototype.initialize.apply(this,[a])},readers:{ogc:OpenLayers.Util.applyDefaults({PropertyIsEqualTo:function(a,b){var c=a.getAttribute("matchCase"),c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,matchCase:!("false"===c||"0"===c)});this.readChildNodes(a,
2097 c);b.filters.push(c)},PropertyIsNotEqualTo:function(a,b){var c=a.getAttribute("matchCase"),c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO,matchCase:!("false"===c||"0"===c)});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsLike:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(a,c);var d=a.getAttribute("wildCard"),e=a.getAttribute("singleChar"),f=a.getAttribute("escapeChar");c.value2regex(d,e,
2098 f);b.filters.push(c)}},OpenLayers.Format.Filter.v1.prototype.readers.ogc),gml:OpenLayers.Format.GML.v3.prototype.readers.gml,feature:OpenLayers.Format.GML.v3.prototype.readers.feature},writers:{ogc:OpenLayers.Util.applyDefaults({PropertyIsEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsEqualTo",{attributes:{matchCase:a.matchCase}});this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsNotEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsNotEqualTo",
2099 {attributes:{matchCase:a.matchCase}});this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsLike:function(a){var b=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{matchCase:a.matchCase,wildCard:"*",singleChar:".",escapeChar:"!"}});this.writeNode("PropertyName",a,b);this.writeNode("Literal",a.regex2value(),b);return b},BBOX:function(a){var b=this.createElementNSPlus("ogc:BBOX");a.property&&this.writeNode("PropertyName",a,b);var c=this.writeNode("gml:Envelope",
2100 a.value);a.projection&&c.setAttribute("srsName",a.projection);b.appendChild(c);return b},SortBy:function(a){for(var b=this.createElementNSPlus("ogc:SortBy"),c=0,d=a.length;c<d;c++)this.writeNode("ogc:SortProperty",a[c],b);return b},SortProperty:function(a){var b=this.createElementNSPlus("ogc:SortProperty");this.writeNode("ogc:PropertyName",a,b);this.writeNode("ogc:SortOrder","DESC"==a.order?"DESC":"ASC",b);return b},SortOrder:function(a){return this.createElementNSPlus("ogc:SortOrder",{value:a})}},
2101 OpenLayers.Format.Filter.v1.prototype.writers.ogc),gml:OpenLayers.Format.GML.v3.prototype.writers.gml,feature:OpenLayers.Format.GML.v3.prototype.writers.feature},writeSpatial:function(a,b){var c=this.createElementNSPlus("ogc:"+b);this.writeNode("PropertyName",a,c);if(a.value instanceof OpenLayers.Filter.Function)this.writeNode("Function",a.value,c);else{var d;d=a.value instanceof OpenLayers.Geometry?this.writeNode("feature:_geometry",a.value).firstChild:this.writeNode("gml:Envelope",a.value);a.projection&&
2102 d.setAttribute("srsName",a.projection);c.appendChild(d)}return c},CLASS_NAME:"OpenLayers.Format.Filter.v1_1_0"});OpenLayers.Format.OWSCommon=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",getVersion:function(a,b){var c=this.version;if(!c){var d=a.getAttribute("xmlns:ows");d&&"1.1"===d.substring(d.lastIndexOf("/")+1)&&(c="1.1.0");c||(c=this.defaultVersion)}return c},CLASS_NAME:"OpenLayers.Format.OWSCommon"});OpenLayers.Format.OWSCommon.v1=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},read:function(a,b){OpenLayers.Util.applyDefaults(b,this.options);var c={};this.readChildNodes(a,c);return c},readers:{ows:{Exception:function(a,b){var c={code:a.getAttribute("exceptionCode"),locator:a.getAttribute("locator"),texts:[]};b.exceptions.push(c);this.readChildNodes(a,c)},ExceptionText:function(a,b){var c=this.getChildValue(a);b.texts.push(c)},
2103 ServiceIdentification:function(a,b){b.serviceIdentification={};this.readChildNodes(a,b.serviceIdentification)},Title:function(a,b){b.title=this.getChildValue(a)},Abstract:function(a,b){b["abstract"]=this.getChildValue(a)},Keywords:function(a,b){b.keywords={};this.readChildNodes(a,b.keywords)},Keyword:function(a,b){b[this.getChildValue(a)]=!0},ServiceType:function(a,b){b.serviceType={codeSpace:a.getAttribute("codeSpace"),value:this.getChildValue(a)}},ServiceTypeVersion:function(a,b){b.serviceTypeVersion=
2104 this.getChildValue(a)},Fees:function(a,b){b.fees=this.getChildValue(a)},AccessConstraints:function(a,b){b.accessConstraints=this.getChildValue(a)},ServiceProvider:function(a,b){b.serviceProvider={};this.readChildNodes(a,b.serviceProvider)},ProviderName:function(a,b){b.providerName=this.getChildValue(a)},ProviderSite:function(a,b){b.providerSite=this.getAttributeNS(a,this.namespaces.xlink,"href")},ServiceContact:function(a,b){b.serviceContact={};this.readChildNodes(a,b.serviceContact)},IndividualName:function(a,
2105 b){b.individualName=this.getChildValue(a)},PositionName:function(a,b){b.positionName=this.getChildValue(a)},ContactInfo:function(a,b){b.contactInfo={};this.readChildNodes(a,b.contactInfo)},Phone:function(a,b){b.phone={};this.readChildNodes(a,b.phone)},Voice:function(a,b){b.voice=this.getChildValue(a)},Address:function(a,b){b.address={};this.readChildNodes(a,b.address)},DeliveryPoint:function(a,b){b.deliveryPoint=this.getChildValue(a)},City:function(a,b){b.city=this.getChildValue(a)},AdministrativeArea:function(a,
2106 b){b.administrativeArea=this.getChildValue(a)},PostalCode:function(a,b){b.postalCode=this.getChildValue(a)},Country:function(a,b){b.country=this.getChildValue(a)},ElectronicMailAddress:function(a,b){b.electronicMailAddress=this.getChildValue(a)},Role:function(a,b){b.role=this.getChildValue(a)},OperationsMetadata:function(a,b){b.operationsMetadata={};this.readChildNodes(a,b.operationsMetadata)},Operation:function(a,b){var c=a.getAttribute("name");b[c]={};this.readChildNodes(a,b[c])},DCP:function(a,
2107 b){b.dcp={};this.readChildNodes(a,b.dcp)},HTTP:function(a,b){b.http={};this.readChildNodes(a,b.http)},Get:function(a,b){b.get||(b.get=[]);var c={url:this.getAttributeNS(a,this.namespaces.xlink,"href")};this.readChildNodes(a,c);b.get.push(c)},Post:function(a,b){b.post||(b.post=[]);var c={url:this.getAttributeNS(a,this.namespaces.xlink,"href")};this.readChildNodes(a,c);b.post.push(c)},Parameter:function(a,b){b.parameters||(b.parameters={});var c=a.getAttribute("name");b.parameters[c]={};this.readChildNodes(a,
2108 b.parameters[c])},Constraint:function(a,b){b.constraints||(b.constraints={});var c=a.getAttribute("name");b.constraints[c]={};this.readChildNodes(a,b.constraints[c])},Value:function(a,b){b[this.getChildValue(a)]=!0},OutputFormat:function(a,b){b.formats.push({value:this.getChildValue(a)});this.readChildNodes(a,b)},WGS84BoundingBox:function(a,b){var c={};c.crs=a.getAttribute("crs");b.BoundingBox?b.BoundingBox.push(c):(b.projection=c.crs,c=b);this.readChildNodes(a,c)},BoundingBox:function(a,b){this.readers.ows.WGS84BoundingBox.apply(this,
2109 [a,b])},LowerCorner:function(a,b){var c=this.getChildValue(a).replace(this.regExes.trimSpace,""),c=c.replace(this.regExes.trimComma,","),c=c.split(this.regExes.splitSpace);b.left=c[0];b.bottom=c[1]},UpperCorner:function(a,b){var c=this.getChildValue(a).replace(this.regExes.trimSpace,""),c=c.replace(this.regExes.trimComma,","),c=c.split(this.regExes.splitSpace);b.right=c[0];b.top=c[1];b.bounds=new OpenLayers.Bounds(b.left,b.bottom,b.right,b.top);delete b.left;delete b.bottom;delete b.right;delete b.top},
2110 Language:function(a,b){b.language=this.getChildValue(a)}}},writers:{ows:{BoundingBox:function(a,b){var c=this.createElementNSPlus(b||"ows:BoundingBox",{attributes:{crs:a.projection}});this.writeNode("ows:LowerCorner",a,c);this.writeNode("ows:UpperCorner",a,c);return c},LowerCorner:function(a){return this.createElementNSPlus("ows:LowerCorner",{value:a.bounds.left+" "+a.bounds.bottom})},UpperCorner:function(a){return this.createElementNSPlus("ows:UpperCorner",{value:a.bounds.right+" "+a.bounds.top})},
2111 Identifier:function(a){return this.createElementNSPlus("ows:Identifier",{value:a})},Title:function(a){return this.createElementNSPlus("ows:Title",{value:a})},Abstract:function(a){return this.createElementNSPlus("ows:Abstract",{value:a})},OutputFormat:function(a){return this.createElementNSPlus("ows:OutputFormat",{value:a})}}},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1"});OpenLayers.Format.OWSCommon.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows",xlink:"http://www.w3.org/1999/xlink"},readers:{ows:OpenLayers.Util.applyDefaults({ExceptionReport:function(a,b){b.success=!1;b.exceptionReport={version:a.getAttribute("version"),language:a.getAttribute("language"),exceptions:[]};this.readChildNodes(a,b.exceptionReport)}},OpenLayers.Format.OWSCommon.v1.prototype.readers.ows)},writers:{ows:OpenLayers.Format.OWSCommon.v1.prototype.writers.ows},
2112 CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_0_0"});OpenLayers.Format.WFST.v1_1_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_1_0,OpenLayers.Format.WFST.v1,{version:"1.1.0",schemaLocations:{wfs:"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"},initialize:function(a){OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this,[a]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[a])},readNode:function(a,b,c){return OpenLayers.Format.GML.v3.prototype.readNode.apply(this,arguments)},readers:{wfs:OpenLayers.Util.applyDefaults({FeatureCollection:function(a,
2113 b){b.numberOfFeatures=parseInt(a.getAttribute("numberOfFeatures"));OpenLayers.Format.WFST.v1.prototype.readers.wfs.FeatureCollection.apply(this,arguments)},TransactionResponse:function(a,b){b.insertIds=[];b.success=!1;this.readChildNodes(a,b)},TransactionSummary:function(a,b){b.success=!0},InsertResults:function(a,b){this.readChildNodes(a,b)},Feature:function(a,b){var c={fids:[]};this.readChildNodes(a,c);b.insertIds.push(c.fids[0])}},OpenLayers.Format.WFST.v1.prototype.readers.wfs),gml:OpenLayers.Format.GML.v3.prototype.readers.gml,
2114 feature:OpenLayers.Format.GML.v3.prototype.readers.feature,ogc:OpenLayers.Format.Filter.v1_1_0.prototype.readers.ogc,ows:OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows},writers:{wfs:OpenLayers.Util.applyDefaults({GetFeature:function(a){var b=OpenLayers.Format.WFST.v1.prototype.writers.wfs.GetFeature.apply(this,arguments);a&&this.setAttributes(b,{resultType:a.resultType,startIndex:a.startIndex,count:a.count});return b},Query:function(a){a=OpenLayers.Util.extend({featureNS:this.featureNS,
2115 featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName},a);var b=a.featurePrefix,c=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(b?b+":":"")+a.featureType,srsName:a.srsName}});a.featureNS&&c.setAttribute("xmlns:"+b,a.featureNS);if(a.propertyNames)for(var b=0,d=a.propertyNames.length;b<d;b++)this.writeNode("wfs:PropertyName",{property:a.propertyNames[b]},c);a.filter&&(OpenLayers.Format.WFST.v1_1_0.prototype.setFilterProperty.call(this,a.filter),this.writeNode("ogc:Filter",
2116 a.filter,c));return c},PropertyName:function(a){return this.createElementNSPlus("wfs:PropertyName",{value:a.property})}},OpenLayers.Format.WFST.v1.prototype.writers.wfs),gml:OpenLayers.Format.GML.v3.prototype.writers.gml,feature:OpenLayers.Format.GML.v3.prototype.writers.feature,ogc:OpenLayers.Format.Filter.v1_1_0.prototype.writers.ogc},CLASS_NAME:"OpenLayers.Format.WFST.v1_1_0"});OpenLayers.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:!0,defaultFilter:null,initialize:function(a){a=a||{};OpenLayers.Util.extend(this,a);this.options=a},mergeWithDefaultFilter:function(a){return a&&this.defaultFilter?new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,a]}):a||this.defaultFilter||void 0},destroy:function(){this.format=this.options=null},read:function(a){a=a||{};a.filter=this.mergeWithDefaultFilter(a.filter)},create:function(){},
2117 update:function(){},"delete":function(){},commit:function(){},abort:function(a){},createCallback:function(a,b,c){return OpenLayers.Function.bind(function(){a.apply(this,[b,c])},this)},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:!0,features:null,data:null,reqFeatures:null,priv:null,error:null,initialize:function(a){OpenLayers.Util.extend(this,a)},success:function(){return 0<this.code},CLASS_NAME:"OpenLayers.Protocol.Response"});
2118 OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:" ",space:" ",newline:"\n",level:0,pretty:!1,nativeJSON:function(){return!(!window.JSON||"function"!=typeof JSON.parse||"function"!=typeof JSON.stringify)}(),read:function(a,b){var c;if(this.nativeJSON)c=JSON.parse(a,b);else try{if(/^[\],:{}\s]*$/.test(a.replace(/\\["\\\/bfnrtu]/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))&&(c=eval("("+a+")"),"function"===
2119 typeof b)){var d=function(a,c){if(c&&"object"===typeof c)for(var e in c)c.hasOwnProperty(e)&&(c[e]=d(e,c[e]));return b(a,c)};c=d("",c)}}catch(e){}this.keepData&&(this.data=c);return c},write:function(a,b){this.pretty=!!b;var c=null,d=typeof a;if(this.serialize[d])try{c=!this.pretty&&this.nativeJSON?JSON.stringify(a):this.serialize[d].apply(this,[a])}catch(e){OpenLayers.Console.error("Trouble serializing: "+e)}return c},writeIndent:function(){var a=[];if(this.pretty)for(var b=0;b<this.level;++b)a.push(this.indent);
2120 return a.join("")},writeNewline:function(){return this.pretty?this.newline:""},writeSpace:function(){return this.pretty?this.space:""},serialize:{object:function(a){if(null==a)return"null";if(a.constructor==Date)return this.serialize.date.apply(this,[a]);if(a.constructor==Array)return this.serialize.array.apply(this,[a]);var b=["{"];this.level+=1;var c,d,e,f=!1;for(c in a)a.hasOwnProperty(c)&&(d=OpenLayers.Format.JSON.prototype.write.apply(this,[c,this.pretty]),e=OpenLayers.Format.JSON.prototype.write.apply(this,
2121 [a[c],this.pretty]),null!=d&&null!=e&&(f&&b.push(","),b.push(this.writeNewline(),this.writeIndent(),d,":",this.writeSpace(),e),f=!0));this.level-=1;b.push(this.writeNewline(),this.writeIndent(),"}");return b.join("")},array:function(a){var b,c=["["];this.level+=1;for(var d=0,e=a.length;d<e;++d)b=OpenLayers.Format.JSON.prototype.write.apply(this,[a[d],this.pretty]),null!=b&&(0<d&&c.push(","),c.push(this.writeNewline(),this.writeIndent(),b));this.level-=1;c.push(this.writeNewline(),this.writeIndent(),
2122 "]");return c.join("")},string:function(a){var b={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};return/["\\\x00-\x1f]/.test(a)?'"'+a.replace(/([\x00-\x1f\\"])/g,function(a,d){var e=b[d];if(e)return e;e=d.charCodeAt();return"\\u00"+Math.floor(e/16).toString(16)+(e%16).toString(16)})+'"':'"'+a+'"'},number:function(a){return isFinite(a)?String(a):"null"},"boolean":function(a){return String(a)},date:function(a){function b(a){return 10>a?"0"+a:a}return'"'+a.getFullYear()+
2123 "-"+b(a.getMonth()+1)+"-"+b(a.getDate())+"T"+b(a.getHours())+":"+b(a.getMinutes())+":"+b(a.getSeconds())+'"'}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:!1,read:function(a,b,c){b=b?b:"FeatureCollection";var d=null,e=null,e="string"==typeof a?OpenLayers.Format.JSON.prototype.read.apply(this,[a,c]):a;if(!e)OpenLayers.Console.error("Bad JSON: "+a);else if("string"!=typeof e.type)OpenLayers.Console.error("Bad GeoJSON - no type: "+a);else if(this.isValidType(e,b))switch(b){case "Geometry":try{d=this.parseGeometry(e)}catch(f){OpenLayers.Console.error(f)}break;case "Feature":try{d=
2124 this.parseFeature(e),d.type="Feature"}catch(g){OpenLayers.Console.error(g)}break;case "FeatureCollection":switch(d=[],e.type){case "Feature":try{d.push(this.parseFeature(e))}catch(h){d=null,OpenLayers.Console.error(h)}break;case "FeatureCollection":a=0;for(b=e.features.length;a<b;++a)try{d.push(this.parseFeature(e.features[a]))}catch(k){d=null,OpenLayers.Console.error(k)}break;default:try{var l=this.parseGeometry(e);d.push(new OpenLayers.Feature.Vector(l))}catch(m){d=null,OpenLayers.Console.error(m)}}}return d},
2125 isValidType:function(a,b){var c=!1;switch(b){case "Geometry":-1==OpenLayers.Util.indexOf("Point MultiPoint LineString MultiLineString Polygon MultiPolygon Box GeometryCollection".split(" "),a.type)?OpenLayers.Console.error("Unsupported geometry type: "+a.type):c=!0;break;case "FeatureCollection":c=!0;break;default:a.type==b?c=!0:OpenLayers.Console.error("Cannot convert types from "+a.type+" to "+b)}return c},parseFeature:function(a){var b,c,d;c=a.properties?a.properties:{};d=a.geometry&&a.geometry.bbox||
2126 a.bbox;try{b=this.parseGeometry(a.geometry)}catch(e){throw e;}b=new OpenLayers.Feature.Vector(b,c);d&&(b.bounds=OpenLayers.Bounds.fromArray(d));a.id&&(b.fid=a.id);return b},parseGeometry:function(a){if(null==a)return null;var b,c=!1;if("GeometryCollection"==a.type){if(!OpenLayers.Util.isArray(a.geometries))throw"GeometryCollection must have geometries array: "+a;b=a.geometries.length;for(var c=Array(b),d=0;d<b;++d)c[d]=this.parseGeometry.apply(this,[a.geometries[d]]);b=new OpenLayers.Geometry.Collection(c);
2127 c=!0}else{if(!OpenLayers.Util.isArray(a.coordinates))throw"Geometry must have coordinates array: "+a;if(!this.parseCoords[a.type.toLowerCase()])throw"Unsupported geometry type: "+a.type;try{b=this.parseCoords[a.type.toLowerCase()].apply(this,[a.coordinates])}catch(e){throw e;}}this.internalProjection&&(this.externalProjection&&!c)&&b.transform(this.externalProjection,this.internalProjection);return b},parseCoords:{point:function(a){if(!1==this.ignoreExtraDims&&2!=a.length)throw"Only 2D points are supported: "+
2128 a;return new OpenLayers.Geometry.Point(a[0],a[1])},multipoint:function(a){for(var b=[],c=null,d=0,e=a.length;d<e;++d){try{c=this.parseCoords.point.apply(this,[a[d]])}catch(f){throw f;}b.push(c)}return new OpenLayers.Geometry.MultiPoint(b)},linestring:function(a){for(var b=[],c=null,d=0,e=a.length;d<e;++d){try{c=this.parseCoords.point.apply(this,[a[d]])}catch(f){throw f;}b.push(c)}return new OpenLayers.Geometry.LineString(b)},multilinestring:function(a){for(var b=[],c=null,d=0,e=a.length;d<e;++d){try{c=
2129 this.parseCoords.linestring.apply(this,[a[d]])}catch(f){throw f;}b.push(c)}return new OpenLayers.Geometry.MultiLineString(b)},polygon:function(a){for(var b=[],c,d,e=0,f=a.length;e<f;++e){try{d=this.parseCoords.linestring.apply(this,[a[e]])}catch(g){throw g;}c=new OpenLayers.Geometry.LinearRing(d.components);b.push(c)}return new OpenLayers.Geometry.Polygon(b)},multipolygon:function(a){for(var b=[],c=null,d=0,e=a.length;d<e;++d){try{c=this.parseCoords.polygon.apply(this,[a[d]])}catch(f){throw f;}b.push(c)}return new OpenLayers.Geometry.MultiPolygon(b)},
2130 box:function(a){if(2!=a.length)throw"GeoJSON box coordinates must have 2 elements";return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(a[0][0],a[0][1]),new OpenLayers.Geometry.Point(a[1][0],a[0][1]),new OpenLayers.Geometry.Point(a[1][0],a[1][1]),new OpenLayers.Geometry.Point(a[0][0],a[1][1]),new OpenLayers.Geometry.Point(a[0][0],a[0][1])])])}},write:function(a,b){var c={type:null};if(OpenLayers.Util.isArray(a)){c.type="FeatureCollection";var d=
2131 a.length;c.features=Array(d);for(var e=0;e<d;++e){var f=a[e];if(!f instanceof OpenLayers.Feature.Vector)throw"FeatureCollection only supports collections of features: "+f;c.features[e]=this.extract.feature.apply(this,[f])}}else 0==a.CLASS_NAME.indexOf("OpenLayers.Geometry")?c=this.extract.geometry.apply(this,[a]):a instanceof OpenLayers.Feature.Vector&&(c=this.extract.feature.apply(this,[a]),a.layer&&a.layer.projection&&(c.crs=this.createCRSObject(a)));return OpenLayers.Format.JSON.prototype.write.apply(this,
2132 [c,b])},createCRSObject:function(a){a=a.layer.projection.toString();var b={};a.match(/epsg:/i)&&(a=parseInt(a.substring(a.indexOf(":")+1)),b=4326==a?{type:"name",properties:{name:"urn:ogc:def:crs:OGC:1.3:CRS84"}}:{type:"name",properties:{name:"EPSG:"+a}});return b},extract:{feature:function(a){var b=this.extract.geometry.apply(this,[a.geometry]),b={type:"Feature",properties:a.attributes,geometry:b};null!=a.fid&&(b.id=a.fid);return b},geometry:function(a){if(null==a)return null;this.internalProjection&&
2133 this.externalProjection&&(a=a.clone(),a.transform(this.internalProjection,this.externalProjection));var b=a.CLASS_NAME.split(".")[2];a=this.extract[b.toLowerCase()].apply(this,[a]);return"Collection"==b?{type:"GeometryCollection",geometries:a}:{type:b,coordinates:a}},point:function(a){return[a.x,a.y]},multipoint:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extract.point.apply(this,[a.components[c]]));return b},linestring:function(a){for(var b=[],c=0,d=a.components.length;c<
2134 d;++c)b.push(this.extract.point.apply(this,[a.components[c]]));return b},multilinestring:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extract.linestring.apply(this,[a.components[c]]));return b},polygon:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extract.linestring.apply(this,[a.components[c]]));return b},multipolygon:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extract.polygon.apply(this,[a.components[c]]));return b},collection:function(a){for(var b=
2135 a.components.length,c=Array(b),d=0;d<b;++d)c[d]=this.extract.geometry.apply(this,[a.components[d]]);return c}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Protocol.Script=OpenLayers.Class(OpenLayers.Protocol,{url:null,params:null,callback:null,callbackTemplate:"OpenLayers.Protocol.Script.registry.${id}",callbackKey:"callback",callbackPrefix:"",scope:null,format:null,pendingRequests:null,srsInBBOX:!1,initialize:function(a){a=a||{};this.params={};this.pendingRequests={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);this.format||(this.format=new OpenLayers.Format.GeoJSON);if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var b=
2136 new OpenLayers.Format.QueryStringFilter({srsInBBOX:this.srsInBBOX});this.filterToParams=function(a,d){return b.write(a,d)}}},read:function(a){OpenLayers.Protocol.prototype.read.apply(this,arguments);a=OpenLayers.Util.applyDefaults(a,this.options);a.params=OpenLayers.Util.applyDefaults(a.params,this.options.params);a.filter&&this.filterToParams&&(a.params=this.filterToParams(a.filter,a.params));var b=new OpenLayers.Protocol.Response({requestType:"read"}),c=this.createRequest(a.url,a.params,OpenLayers.Function.bind(function(c){b.data=
2137 c;this.handleRead(b,a)},this));b.priv=c;return b},createRequest:function(a,b,c){c=OpenLayers.Protocol.Script.register(c);var d=OpenLayers.String.format(this.callbackTemplate,{id:c});b=OpenLayers.Util.extend({},b);b[this.callbackKey]=this.callbackPrefix+d;a=OpenLayers.Util.urlAppend(a,OpenLayers.Util.getParameterString(b));b=document.createElement("script");b.type="text/javascript";b.src=a;b.id="OpenLayers_Protocol_Script_"+c;this.pendingRequests[b.id]=b;document.getElementsByTagName("head")[0].appendChild(b);
2138 return b},destroyRequest:function(a){OpenLayers.Protocol.Script.unregister(a.id.split("_").pop());delete this.pendingRequests[a.id];a.parentNode&&a.parentNode.removeChild(a)},handleRead:function(a,b){this.handleResponse(a,b)},handleResponse:function(a,b){b.callback&&(a.data?(a.features=this.parseFeatures(a.data),a.code=OpenLayers.Protocol.Response.SUCCESS):a.code=OpenLayers.Protocol.Response.FAILURE,this.destroyRequest(a.priv),b.callback.call(b.scope,a))},parseFeatures:function(a){return this.format.read(a)},
2139 abort:function(a){if(a)this.destroyRequest(a.priv);else for(var b in this.pendingRequests)this.destroyRequest(this.pendingRequests[b])},destroy:function(){this.abort();delete this.params;delete this.format;OpenLayers.Protocol.prototype.destroy.apply(this)},CLASS_NAME:"OpenLayers.Protocol.Script"});(function(){var a=OpenLayers.Protocol.Script,b=0;a.registry={};a.register=function(c){var d="c"+ ++b;a.registry[d]=function(){c.apply(this,arguments)};return d};a.unregister=function(b){delete a.registry[b]}})();OpenLayers.Format.EncodedPolyline=OpenLayers.Class(OpenLayers.Format,{geometryType:"linestring",initialize:function(a){OpenLayers.Format.prototype.initialize.apply(this,[a])},read:function(a){var b;if("linestring"==this.geometryType)b=OpenLayers.Geometry.LineString;else if("linearring"==this.geometryType)b=OpenLayers.Geometry.LinearRing;else if("multipoint"==this.geometryType)b=OpenLayers.Geometry.MultiPoint;else if("point"!=this.geometryType&&"polygon"!=this.geometryType)return null;a=this.decodeDeltas(a,
2140 2);for(var c=a.length,d=[],e=0;e+1<c;){var f=a[e++],g=a[e++];d.push(new OpenLayers.Geometry.Point(g,f))}return"point"==this.geometryType?new OpenLayers.Feature.Vector(d[0]):"polygon"==this.geometryType?new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(d)])):new OpenLayers.Feature.Vector(new b(d))},decode:function(a,b,c){a=this.decodeDeltas(a,b,c||1E5);c=a.length;for(var d=[],e=0;e+(b-1)<c;){for(var f=[],g=0;g<b;++g)f.push(a[e++]);d.push(f)}return d},
2141 write:function(a){a=(a.constructor==Array?a[0]:a).geometry;var b=a.CLASS_NAME.split(".")[2].toLowerCase();if("point"==b)a=Array(a);else if("linestring"==b||"linearring"==b||"multipoint"==b)a=a.components;else if("polygon"==b)a=a.components[0].components;else return null;for(var b=[],c=a.length,d=0;d<c;++d){var e=a[d];b.push(e.y);b.push(e.x)}return this.encodeDeltas(b,2)},encode:function(a,b,c){c=c||1E5;for(var d=[],e=a.length,f=0;f<e;++f)for(var g=a[f],h=0;h<b;++h)d.push(g[h]);return this.encodeDeltas(d,
2142 b,c)},encodeDeltas:function(a,b,c){var d,e=Array(b);for(d=0;d<b;++d)e[d]=0;for(var f=a.length,g=0;g<f;)for(d=0;d<b;++d,++g){var h=a[g],k=h-e[d];e[d]=h;a[g]=k}return this.encodeFloats(a,c||1E5)},decodeDeltas:function(a,b,c){var d,e=Array(b);for(d=0;d<b;++d)e[d]=0;a=this.decodeFloats(a,c||1E5);c=a.length;for(var f=0;f<c;)for(d=0;d<b;++d,++f)e[d]+=a[f],a[f]=e[d];return a},encodeFloats:function(a,b){for(var c=b||1E5,d=a.length,e=0;e<d;++e)a[e]=Math.round(a[e]*c);return this.encodeSignedIntegers(a)},decodeFloats:function(a,
2143 b){for(var c=b||1E5,d=this.decodeSignedIntegers(a),e=d.length,f=0;f<e;++f)d[f]/=c;return d},encodeSignedIntegers:function(a){for(var b=a.length,c=0;c<b;++c){var d=a[c],e=d<<1;0>d&&(e=~e);a[c]=e}return this.encodeUnsignedIntegers(a)},decodeSignedIntegers:function(a){a=this.decodeUnsignedIntegers(a);for(var b=a.length,c=0;c<b;++c){var d=a[c];a[c]=d&1?~(d>>1):d>>1}return a},encodeUnsignedIntegers:function(a){for(var b="",c=a.length,d=0;d<c;++d)b+=this.encodeUnsignedInteger(a[d]);return b},decodeUnsignedIntegers:function(a){for(var b=
2144 [],c=0,d=0,e=a.length,f=0;f<e;++f){var g=a.charCodeAt(f)-63,c=c|(g&31)<<d;32>g?(b.push(c),d=c=0):d+=5}return b},encodeFloat:function(a,b){a=Math.round(a*(b||1E5));return this.encodeSignedInteger(a)},decodeFloat:function(a,b){return this.decodeSignedInteger(a)/(b||1E5)},encodeSignedInteger:function(a){var b=a<<1;0>a&&(b=~b);return this.encodeUnsignedInteger(b)},decodeSignedInteger:function(a){a=this.decodeUnsignedInteger(a);return a&1?~(a>>1):a>>1},encodeUnsignedInteger:function(a){for(var b,c="";32<=
2145 a;)b=(32|a&31)+63,c+=String.fromCharCode(b),a>>=5;return c+=String.fromCharCode(a+63)},decodeUnsignedInteger:function(a){for(var b=0,c=0,d=a.length,e=0;e<d;++e){var f=a.charCodeAt(e)-63,b=b|(f&31)<<c;if(32>f)break;c+=5}return b},CLASS_NAME:"OpenLayers.Format.EncodedPolyline"});OpenLayers.Control.Panel=OpenLayers.Class(OpenLayers.Control,{controls:null,autoActivate:!0,defaultControl:null,saveState:!1,allowDepress:!1,activeState:null,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,[a]);this.controls=[];this.activeState={}},destroy:function(){this.map&&this.map.events.unregister("buttonclick",this,this.onButtonClick);OpenLayers.Control.prototype.destroy.apply(this,arguments);for(var a,b=this.controls.length-1;0<=b;b--)a=this.controls[b],a.events&&
2146 a.events.un({activate:this.iconOn,deactivate:this.iconOff}),a.panel_div=null;this.activeState=null},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){for(var a,b=0,c=this.controls.length;b<c;b++)a=this.controls[b],(a===this.defaultControl||this.saveState&&this.activeState[a.id])&&a.activate();!0===this.saveState&&(this.defaultControl=null);this.redraw();return!0}return!1},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){for(var a,
2147 b=0,c=this.controls.length;b<c;b++)a=this.controls[b],this.activeState[a.id]=a.deactivate();this.redraw();return!0}return!1},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.outsideViewport?(this.events.attachToElement(this.div),this.events.register("buttonclick",this,this.onButtonClick)):this.map.events.register("buttonclick",this,this.onButtonClick);this.addControlsToMap(this.controls);return this.div},redraw:function(){for(var a=this.div.childNodes.length-1;0<=a;a--)this.div.removeChild(this.div.childNodes[a]);
2148 this.div.innerHTML="";if(this.active)for(var a=0,b=this.controls.length;a<b;a++)this.div.appendChild(this.controls[a].panel_div)},activateControl:function(a){if(!this.active)return!1;if(a.type==OpenLayers.Control.TYPE_BUTTON)a.trigger();else if(a.type==OpenLayers.Control.TYPE_TOGGLE)a.active?a.deactivate():a.activate();else if(this.allowDepress&&a.active)a.deactivate();else{for(var b,c=0,d=this.controls.length;c<d;c++)b=this.controls[c],b==a||b.type!==OpenLayers.Control.TYPE_TOOL&&null!=b.type||b.deactivate();
2149 a.activate()}},addControls:function(a){OpenLayers.Util.isArray(a)||(a=[a]);this.controls=this.controls.concat(a);for(var b=0,c=a.length;b<c;b++){var d=a[b],e=this.createControlMarkup(d);OpenLayers.Element.addClass(e,d.displayClass+"ItemInactive");OpenLayers.Element.addClass(e,"olButton");""==d.title||e.title||(e.title=d.title);d.panel_div=e}this.map&&(this.addControlsToMap(a),this.redraw())},createControlMarkup:function(a){return document.createElement("div")},addControlsToMap:function(a){for(var b,
2150 c=0,d=a.length;c<d;c++)b=a[c],!0===b.autoActivate?(b.autoActivate=!1,this.map.addControl(b),b.autoActivate=!0):(this.map.addControl(b),b.deactivate()),b.events.on({activate:this.iconOn,deactivate:this.iconOff})},iconOn:function(){var a=this.panel_div;a.className=a.className.replace(RegExp("\\b("+this.displayClass+"Item)Inactive\\b"),"$1Active")},iconOff:function(){var a=this.panel_div;a.className=a.className.replace(RegExp("\\b("+this.displayClass+"Item)Active\\b"),"$1Inactive")},onButtonClick:function(a){var b=
2151 this.controls;a=a.buttonElement;for(var c=b.length-1;0<=c;--c)if(b[c].panel_div===a){this.activateControl(b[c]);break}},getControlsBy:function(a,b){var c="function"==typeof b.test;return OpenLayers.Array.filter(this.controls,function(d){return d[a]==b||c&&b.test(d[a])})},getControlsByName:function(a){return this.getControlsBy("name",a)},getControlsByClass:function(a){return this.getControlsBy("CLASS_NAME",a)},CLASS_NAME:"OpenLayers.Control.Panel"});OpenLayers.Control.Button=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){},CLASS_NAME:"OpenLayers.Control.Button"});OpenLayers.Control.ZoomIn=OpenLayers.Class(OpenLayers.Control.Button,{trigger:function(){this.map&&this.map.zoomIn()},CLASS_NAME:"OpenLayers.Control.ZoomIn"});OpenLayers.Control.ZoomOut=OpenLayers.Class(OpenLayers.Control.Button,{trigger:function(){this.map&&this.map.zoomOut()},CLASS_NAME:"OpenLayers.Control.ZoomOut"});OpenLayers.Control.ZoomToMaxExtent=OpenLayers.Class(OpenLayers.Control.Button,{trigger:function(){this.map&&this.map.zoomToMaxExtent()},CLASS_NAME:"OpenLayers.Control.ZoomToMaxExtent"});OpenLayers.Control.ZoomPanel=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(a){OpenLayers.Control.Panel.prototype.initialize.apply(this,[a]);this.addControls([new OpenLayers.Control.ZoomIn,new OpenLayers.Control.ZoomToMaxExtent,new OpenLayers.Control.ZoomOut])},CLASS_NAME:"OpenLayers.Control.ZoomPanel"});OpenLayers.Layer.HTTPRequest=OpenLayers.Class(OpenLayers.Layer,{URL_HASH_FACTOR:(Math.sqrt(5)-1)/2,url:null,params:null,reproject:!1,initialize:function(a,b,c,d){OpenLayers.Layer.prototype.initialize.apply(this,[a,d]);this.url=b;this.params||(this.params=OpenLayers.Util.extend({},c))},destroy:function(){this.params=this.url=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments)},clone:function(a){null==a&&(a=new OpenLayers.Layer.HTTPRequest(this.name,this.url,this.params,this.getOptions()));
2152 return a=OpenLayers.Layer.prototype.clone.apply(this,[a])},setUrl:function(a){this.url=a},mergeNewParams:function(a){this.params=OpenLayers.Util.extend(this.params,a);a=this.redraw();null!=this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"params"});return a},redraw:function(a){return a?this.mergeNewParams({_olSalt:Math.random()}):OpenLayers.Layer.prototype.redraw.apply(this,[])},selectUrl:function(a,b){for(var c=1,d=0,e=a.length;d<e;d++)c*=a.charCodeAt(d)*this.URL_HASH_FACTOR,
2153 c-=Math.floor(c);return b[Math.floor(c*b.length)]},getFullRequestString:function(a,b){var c=b||this.url,d=OpenLayers.Util.extend({},this.params),d=OpenLayers.Util.extend(d,a),e=OpenLayers.Util.getParameterString(d);OpenLayers.Util.isArray(c)&&(c=this.selectUrl(e,c));var e=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(c)),f;for(f in d)f.toUpperCase()in e&&delete d[f];e=OpenLayers.Util.getParameterString(d);return OpenLayers.Util.urlAppend(c,e)},CLASS_NAME:"OpenLayers.Layer.HTTPRequest"});OpenLayers.Tile=OpenLayers.Class({events:null,eventListeners:null,id:null,layer:null,url:null,bounds:null,size:null,position:null,isLoading:!1,initialize:function(a,b,c,d,e,f){this.layer=a;this.position=b.clone();this.setBounds(c);this.url=d;e&&(this.size=e.clone());this.id=OpenLayers.Util.createUniqueID("Tile_");OpenLayers.Util.extend(this,f);this.events=new OpenLayers.Events(this);if(this.eventListeners instanceof Object)this.events.on(this.eventListeners)},unload:function(){this.isLoading&&(this.isLoading=
2154 !1,this.events.triggerEvent("unload"))},destroy:function(){this.position=this.size=this.bounds=this.layer=null;this.eventListeners&&this.events.un(this.eventListeners);this.events.destroy();this.events=this.eventListeners=null},draw:function(a){a||this.clear();var b=this.shouldDraw();b&&(!a&&!1===this.events.triggerEvent("beforedraw"))&&(b=null);return b},shouldDraw:function(){var a=!1,b=this.layer.maxExtent;if(b){var c=this.layer.map,c=c.baseLayer.wrapDateLine&&c.getMaxExtent();this.bounds.intersectsBounds(b,
2155 {inclusive:!1,worldBounds:c})&&(a=!0)}return a||this.layer.displayOutsideMaxExtent},setBounds:function(a){a=a.clone();if(this.layer.map.baseLayer.wrapDateLine){var b=this.layer.map.getMaxExtent(),c=this.layer.map.getResolution();a=a.wrapDateLine(b,{leftTolerance:c,rightTolerance:c})}this.bounds=a},moveTo:function(a,b,c){null==c&&(c=!0);this.setBounds(a);this.position=b.clone();c&&this.draw()},clear:function(a){},CLASS_NAME:"OpenLayers.Tile"});OpenLayers.Tile.Image=OpenLayers.Class(OpenLayers.Tile,{url:null,imgDiv:null,frame:null,imageReloadAttempts:null,layerAlphaHack:null,asyncRequestId:null,maxGetUrlLength:null,canvasContext:null,crossOriginKeyword:null,initialize:function(a,b,c,d,e,f){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=d;this.layerAlphaHack=this.layer.alpha&&OpenLayers.Util.alphaHack();if(null!=this.maxGetUrlLength||this.layer.gutter||this.layerAlphaHack)this.frame=document.createElement("div"),this.frame.style.position=
2156 "absolute",this.frame.style.overflow="hidden";null!=this.maxGetUrlLength&&OpenLayers.Util.extend(this,OpenLayers.Tile.Image.IFrame)},destroy:function(){this.imgDiv&&(this.clear(),this.frame=this.imgDiv=null);this.asyncRequestId=null;OpenLayers.Tile.prototype.destroy.apply(this,arguments)},draw:function(){var a=OpenLayers.Tile.prototype.draw.apply(this,arguments);a?(this.layer!=this.layer.map.baseLayer&&this.layer.reproject&&(this.bounds=this.getBoundsFromBaseLayer(this.position)),this.isLoading?this._loadEvent=
2157 "reload":(this.isLoading=!0,this._loadEvent="loadstart"),this.renderTile(),this.positionTile()):!1===a&&this.unload();return a},renderTile:function(){if(this.layer.async){var a=this.asyncRequestId=(this.asyncRequestId||0)+1;this.layer.getURLasync(this.bounds,function(b){a==this.asyncRequestId&&(this.url=b,this.initImage())},this)}else this.url=this.layer.getURL(this.bounds),this.initImage()},positionTile:function(){var a=this.getTile().style,b=this.frame?this.size:this.layer.getImageSize(this.bounds),
2158 c=1;this.layer instanceof OpenLayers.Layer.Grid&&(c=this.layer.getServerResolution()/this.layer.map.getResolution());a.left=this.position.x+"px";a.top=this.position.y+"px";a.width=Math.round(c*b.w)+"px";a.height=Math.round(c*b.h)+"px"},clear:function(){OpenLayers.Tile.prototype.clear.apply(this,arguments);var a=this.imgDiv;if(a){var b=this.getTile();b.parentNode===this.layer.div&&this.layer.div.removeChild(b);this.setImgSrc();!0===this.layerAlphaHack&&(a.style.filter="");OpenLayers.Element.removeClass(a,
2159 "olImageLoadError")}this.canvasContext=null},getImage:function(){if(!this.imgDiv){this.imgDiv=OpenLayers.Tile.Image.IMAGE.cloneNode(!1);var a=this.imgDiv.style;if(this.frame){var b=0,c=0;this.layer.gutter&&(b=100*(this.layer.gutter/this.layer.tileSize.w),c=100*(this.layer.gutter/this.layer.tileSize.h));a.left=-b+"%";a.top=-c+"%";a.width=2*b+100+"%";a.height=2*c+100+"%"}a.visibility="hidden";a.opacity=0;1>this.layer.opacity&&(a.filter="alpha(opacity="+100*this.layer.opacity+")");a.position="absolute";
2160 this.layerAlphaHack&&(a.paddingTop=a.height,a.height="0",a.width="100%");this.frame&&this.frame.appendChild(this.imgDiv)}return this.imgDiv},setImage:function(a){this.imgDiv=a},initImage:function(){if(this.url||this.imgDiv){this.events.triggerEvent("beforeload");this.layer.div.appendChild(this.getTile());this.events.triggerEvent(this._loadEvent);var a=this.getImage(),b=a.getAttribute("src")||"";this.url&&OpenLayers.Util.isEquivalentUrl(b,this.url)?this._loadTimeout=window.setTimeout(OpenLayers.Function.bind(this.onImageLoad,
2161 this),0):(this.stopLoading(),this.crossOriginKeyword&&a.removeAttribute("crossorigin"),OpenLayers.Event.observe(a,"load",OpenLayers.Function.bind(this.onImageLoad,this)),OpenLayers.Event.observe(a,"error",OpenLayers.Function.bind(this.onImageError,this)),this.imageReloadAttempts=0,this.setImgSrc(this.url))}else this.isLoading=!1},setImgSrc:function(a){var b=this.imgDiv;a?(b.style.visibility="hidden",b.style.opacity=0,this.crossOriginKeyword&&("data:"!==a.substr(0,5)?b.setAttribute("crossorigin",this.crossOriginKeyword):
2162 b.removeAttribute("crossorigin")),b.src=a):(this.stopLoading(),this.imgDiv=null,b.parentNode&&b.parentNode.removeChild(b))},getTile:function(){return this.frame?this.frame:this.getImage()},createBackBuffer:function(){if(this.imgDiv&&!this.isLoading){var a;this.frame?(a=this.frame.cloneNode(!1),a.appendChild(this.imgDiv)):a=this.imgDiv;this.imgDiv=null;return a}},onImageLoad:function(){var a=this.imgDiv;this.stopLoading();a.style.visibility="inherit";a.style.opacity=this.layer.opacity;this.isLoading=
2163 !1;this.canvasContext=null;this.events.triggerEvent("loadend");!0===this.layerAlphaHack&&(a.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+a.src+"', sizingMethod='scale')")},onImageError:function(){var a=this.imgDiv;null!=a.src&&(this.imageReloadAttempts++,this.imageReloadAttempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS?this.setImgSrc(this.layer.getURL(this.bounds)):(OpenLayers.Element.addClass(a,"olImageLoadError"),this.events.triggerEvent("loaderror"),this.onImageLoad()))},stopLoading:function(){OpenLayers.Event.stopObservingElement(this.imgDiv);
2164 window.clearTimeout(this._loadTimeout);delete this._loadTimeout},getCanvasContext:function(){if(OpenLayers.CANVAS_SUPPORTED&&this.imgDiv&&!this.isLoading){if(!this.canvasContext){var a=document.createElement("canvas");a.width=this.size.w;a.height=this.size.h;this.canvasContext=a.getContext("2d");this.canvasContext.drawImage(this.imgDiv,0,0)}return this.canvasContext}},CLASS_NAME:"OpenLayers.Tile.Image"});
2165 OpenLayers.Tile.Image.IMAGE=function(){var a=new Image;a.className="olTileImage";a.galleryImg="no";return a}();OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,tileOriginCorner:"bl",tileOrigin:null,tileOptions:null,tileClass:OpenLayers.Tile.Image,grid:null,singleTile:!1,ratio:1.5,buffer:0,transitionEffect:"resize",numLoadingTiles:0,serverResolutions:null,loading:!1,backBuffer:null,gridResolution:null,backBufferResolution:null,backBufferLonLat:null,backBufferTimerId:null,removeBackBufferDelay:null,className:null,gridLayout:null,rowSign:null,transitionendEvents:["transitionend",
2166 "webkitTransitionEnd","otransitionend","oTransitionEnd"],initialize:function(a,b,c,d){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.grid=[];this._removeBackBuffer=OpenLayers.Function.bind(this.removeBackBuffer,this);this.initProperties();this.rowSign="t"===this.tileOriginCorner.substr(0,1)?1:-1},initProperties:function(){void 0===this.options.removeBackBufferDelay&&(this.removeBackBufferDelay=this.singleTile?0:2500);void 0===this.options.className&&(this.className=this.singleTile?
2167 "olLayerGridSingleTile":"olLayerGrid")},setMap:function(a){OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this,a);OpenLayers.Element.addClass(this.div,this.className)},removeMap:function(a){this.removeBackBuffer()},destroy:function(){this.removeBackBuffer();this.clearGrid();this.tileSize=this.grid=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments)},clearGrid:function(){if(this.grid){for(var a=0,b=this.grid.length;a<b;a++)for(var c=this.grid[a],d=0,e=c.length;d<e;d++)this.destroyTile(c[d]);
2168 this.grid=[];this.gridLayout=this.gridResolution=null}},addOptions:function(a,b){var c=void 0!==a.singleTile&&a.singleTile!==this.singleTile;OpenLayers.Layer.HTTPRequest.prototype.addOptions.apply(this,arguments);this.map&&c&&(this.initProperties(),this.clearGrid(),this.tileSize=this.options.tileSize,this.setTileSize(),this.moveTo(null,!0))},clone:function(a){null==a&&(a=new OpenLayers.Layer.Grid(this.name,this.url,this.params,this.getOptions()));a=OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,
2169 [a]);null!=this.tileSize&&(a.tileSize=this.tileSize.clone());a.grid=[];a.gridResolution=null;a.backBuffer=null;a.backBufferTimerId=null;a.loading=!1;a.numLoadingTiles=0;return a},moveTo:function(a,b,c){OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this,arguments);a=a||this.map.getExtent();if(null!=a){var d=!this.grid.length||b,e=this.getTilesBounds(),f=this.map.getResolution();this.getServerResolution(f);if(this.singleTile){if(d||!c&&!e.containsBounds(a))b&&"resize"!==this.transitionEffect&&
2170 this.removeBackBuffer(),b&&"resize"!==this.transitionEffect||this.applyBackBuffer(f),this.initSingleTile(a)}else(d=d||!e.intersectsBounds(a,{worldBounds:this.map.baseLayer.wrapDateLine&&this.map.getMaxExtent()}))?(!b||"resize"!==this.transitionEffect&&this.gridResolution!==f||this.applyBackBuffer(f),this.initGriddedTiles(a)):this.moveGriddedTiles()}},getTileData:function(a){var b=null,c=a.lon,d=a.lat,e=this.grid.length;if(this.map&&e){var f=this.map.getResolution();a=this.tileSize.w;var g=this.tileSize.h,
2171 h=this.grid[0][0].bounds,k=h.left,h=h.top;if(c<k&&this.map.baseLayer.wrapDateLine)var l=this.map.getMaxExtent().getWidth(),m=Math.ceil((k-c)/l),c=c+l*m;c=(c-k)/(f*a);d=(h-d)/(f*g);f=Math.floor(c);k=Math.floor(d);0<=k&&k<e&&(e=this.grid[k][f])&&(b={tile:e,i:Math.floor((c-f)*a),j:Math.floor((d-k)*g)})}return b},destroyTile:function(a){this.removeTileMonitoringHooks(a);a.destroy()},getServerResolution:function(a){var b=Number.POSITIVE_INFINITY;a=a||this.map.getResolution();if(this.serverResolutions&&
2172 -1===OpenLayers.Util.indexOf(this.serverResolutions,a)){var c,d,e,f;for(c=this.serverResolutions.length-1;0<=c;c--){e=this.serverResolutions[c];d=Math.abs(e-a);if(d>b)break;b=d;f=e}a=f}return a},getServerZoom:function(){var a=this.getServerResolution();return this.serverResolutions?OpenLayers.Util.indexOf(this.serverResolutions,a):this.map.getZoomForResolution(a)+(this.zoomOffset||0)},applyBackBuffer:function(a){null!==this.backBufferTimerId&&this.removeBackBuffer();var b=this.backBuffer;if(!b){b=
2173 this.createBackBuffer();if(!b)return;a===this.gridResolution?this.div.insertBefore(b,this.div.firstChild):this.map.baseLayer.div.parentNode.insertBefore(b,this.map.baseLayer.div);this.backBuffer=b;var c=this.grid[0][0].bounds;this.backBufferLonLat={lon:c.left,lat:c.top};this.backBufferResolution=this.gridResolution}for(var c=this.backBufferResolution/a,d=b.childNodes,e,f=d.length-1;0<=f;--f)e=d[f],e.style.top=(c*e._i*e._h|0)+"px",e.style.left=(c*e._j*e._w|0)+"px",e.style.width=Math.round(c*e._w)+
2174 "px",e.style.height=Math.round(c*e._h)+"px";a=this.getViewPortPxFromLonLat(this.backBufferLonLat,a);c=this.map.layerContainerOriginPx.y;b.style.left=Math.round(a.x-this.map.layerContainerOriginPx.x)+"px";b.style.top=Math.round(a.y-c)+"px"},createBackBuffer:function(){var a;if(0<this.grid.length){a=document.createElement("div");a.id=this.div.id+"_bb";a.className="olBackBuffer";a.style.position="absolute";var b=this.map;a.style.zIndex="resize"===this.transitionEffect?this.getZIndex()-1:b.Z_INDEX_BASE.BaseLayer-
2175 (b.getNumLayers()-b.getLayerIndex(this));for(var b=0,c=this.grid.length;b<c;b++)for(var d=0,e=this.grid[b].length;d<e;d++){var f=this.grid[b][d],g=this.grid[b][d].createBackBuffer();g&&(g._i=b,g._j=d,g._w=f.size.w,g._h=f.size.h,g.id=f.id+"_bb",a.appendChild(g))}}return a},removeBackBuffer:function(){if(this._transitionElement){for(var a=this.transitionendEvents.length-1;0<=a;--a)OpenLayers.Event.stopObserving(this._transitionElement,this.transitionendEvents[a],this._removeBackBuffer);delete this._transitionElement}this.backBuffer&&
2176 (this.backBuffer.parentNode&&this.backBuffer.parentNode.removeChild(this.backBuffer),this.backBufferResolution=this.backBuffer=null,null!==this.backBufferTimerId&&(window.clearTimeout(this.backBufferTimerId),this.backBufferTimerId=null))},moveByPx:function(a,b){this.singleTile||this.moveGriddedTiles()},setTileSize:function(a){this.singleTile&&(a=this.map.getSize(),a.h=parseInt(a.h*this.ratio,10),a.w=parseInt(a.w*this.ratio,10));OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this,[a])},getTilesBounds:function(){var a=
2177 null,b=this.grid.length;if(b)var a=this.grid[b-1][0].bounds,b=this.grid[0].length*a.getWidth(),c=this.grid.length*a.getHeight(),a=new OpenLayers.Bounds(a.left,a.bottom,a.left+b,a.bottom+c);return a},initSingleTile:function(a){this.events.triggerEvent("retile");var b=a.getCenterLonLat(),c=a.getWidth()*this.ratio;a=a.getHeight()*this.ratio;b=new OpenLayers.Bounds(b.lon-c/2,b.lat-a/2,b.lon+c/2,b.lat+a/2);c=this.map.getLayerPxFromLonLat({lon:b.left,lat:b.top});this.grid.length||(this.grid[0]=[]);(a=this.grid[0][0])?
2178 a.moveTo(b,c):(a=this.addTile(b,c),this.addTileMonitoringHooks(a),a.draw(),this.grid[0][0]=a);this.removeExcessTiles(1,1);this.gridResolution=this.getServerResolution()},calculateGridLayout:function(a,b,c){var d=c*this.tileSize.w;c*=this.tileSize.h;var e=Math.floor((a.left-b.lon)/d)-this.buffer,f=this.rowSign;a=Math[~f?"floor":"ceil"](f*(b.lat-a.top+c)/c)-this.buffer*f;return{tilelon:d,tilelat:c,startcol:e,startrow:a}},getTileOrigin:function(){var a=this.tileOrigin;if(!a)var a=this.getMaxExtent(),
2179 b={tl:["left","top"],tr:["right","top"],bl:["left","bottom"],br:["right","bottom"]}[this.tileOriginCorner],a=new OpenLayers.LonLat(a[b[0]],a[b[1]]);return a},getTileBoundsForGridIndex:function(a,b){var c=this.getTileOrigin(),d=this.gridLayout,e=d.tilelon,f=d.tilelat,g=d.startcol,d=d.startrow,h=this.rowSign;return new OpenLayers.Bounds(c.lon+(g+b)*e,c.lat-(d+a*h)*f*h,c.lon+(g+b+1)*e,c.lat-(d+(a-1)*h)*f*h)},initGriddedTiles:function(a){this.events.triggerEvent("retile");var b=this.map.getSize(),c=this.getTileOrigin(),
2180 d=this.map.getResolution(),e=this.getServerResolution(),f=d/e,d=this.tileSize.w/f,f=this.tileSize.h/f,g=Math.ceil(b.h/f)+2*this.buffer+1,b=Math.ceil(b.w/d)+2*this.buffer+1;this.gridLayout=e=this.calculateGridLayout(a,c,e);var c=e.tilelon,h=e.tilelat,e=this.map.layerContainerOriginPx.x,k=this.map.layerContainerOriginPx.y,l=this.getTileBoundsForGridIndex(0,0),m=this.map.getViewPortPxFromLonLat(new OpenLayers.LonLat(l.left,l.top));m.x=Math.round(m.x)-e;m.y=Math.round(m.y)-k;var e=[],k=this.map.getCenter(),
2181 n=0;do{var p=this.grid[n];p||(p=[],this.grid.push(p));var q=0;do{var l=this.getTileBoundsForGridIndex(n,q),r=m.clone();r.x+=q*Math.round(d);r.y+=n*Math.round(f);var s=p[q];s?s.moveTo(l,r,!1):(s=this.addTile(l,r),this.addTileMonitoringHooks(s),p.push(s));r=l.getCenterLonLat();e.push({tile:s,distance:Math.pow(r.lon-k.lon,2)+Math.pow(r.lat-k.lat,2)});q+=1}while(l.right<=a.right+c*this.buffer||q<b);n+=1}while(l.bottom>=a.bottom-h*this.buffer||n<g);this.removeExcessTiles(n,q);this.gridResolution=d=this.getServerResolution();
2182 e.sort(function(a,b){return a.distance-b.distance});a=0;for(d=e.length;a<d;++a)e[a].tile.draw()},getMaxExtent:function(){return this.maxExtent},addTile:function(a,b){var c=new this.tileClass(this,b,a,null,this.tileSize,this.tileOptions);this.events.triggerEvent("addtile",{tile:c});return c},addTileMonitoringHooks:function(a){a.onLoadStart=function(){!1===this.loading&&(this.loading=!0,this.events.triggerEvent("loadstart"));this.events.triggerEvent("tileloadstart",{tile:a});this.numLoadingTiles++;
2183 !this.singleTile&&(this.backBuffer&&this.gridResolution===this.backBufferResolution)&&OpenLayers.Element.addClass(a.getTile(),"olTileReplacing")};a.onLoadEnd=function(b){this.numLoadingTiles--;b="unload"===b.type;this.events.triggerEvent("tileloaded",{tile:a,aborted:b});if(!this.singleTile&&!b&&this.backBuffer&&this.gridResolution===this.backBufferResolution){var c=a.getTile();if("none"===OpenLayers.Element.getStyle(c,"display")){var d=document.getElementById(a.id+"_bb");d&&d.parentNode.removeChild(d)}OpenLayers.Element.removeClass(c,
2184 "olTileReplacing")}if(0===this.numLoadingTiles){if(this.backBuffer)if(0===this.backBuffer.childNodes.length)this.removeBackBuffer();else{this._transitionElement=b?this.div.lastChild:a.imgDiv;b=this.transitionendEvents;for(c=b.length-1;0<=c;--c)OpenLayers.Event.observe(this._transitionElement,b[c],this._removeBackBuffer);this.backBufferTimerId=window.setTimeout(this._removeBackBuffer,this.removeBackBufferDelay)}this.loading=!1;this.events.triggerEvent("loadend")}};a.onLoadError=function(){this.events.triggerEvent("tileerror",
2185 {tile:a})};a.events.on({loadstart:a.onLoadStart,loadend:a.onLoadEnd,unload:a.onLoadEnd,loaderror:a.onLoadError,scope:this})},removeTileMonitoringHooks:function(a){a.unload();a.events.un({loadstart:a.onLoadStart,loadend:a.onLoadEnd,unload:a.onLoadEnd,loaderror:a.onLoadError,scope:this})},moveGriddedTiles:function(){for(var a=this.buffer+1;;){var b=this.grid[0][0],c=b.position.x+this.map.layerContainerOriginPx.x,b=b.position.y+this.map.layerContainerOriginPx.y,d=this.getServerResolution()/this.map.getResolution(),
2186 d={w:Math.round(this.tileSize.w*d),h:Math.round(this.tileSize.h*d)};if(c>-d.w*(a-1))this.shiftColumn(!0,d);else if(c<-d.w*a)this.shiftColumn(!1,d);else if(b>-d.h*(a-1))this.shiftRow(!0,d);else if(b<-d.h*a)this.shiftRow(!1,d);else break}},shiftRow:function(a,b){var c=this.grid,d=a?0:c.length-1,e=a?-1:1;this.gridLayout.startrow+=e*this.rowSign;for(var f=c[d],g=c[a?"pop":"shift"](),h=0,k=g.length;h<k;h++){var l=g[h],m=f[h].position.clone();m.y+=b.h*e;l.moveTo(this.getTileBoundsForGridIndex(d,h),m)}c[a?
2187 "unshift":"push"](g)},shiftColumn:function(a,b){var c=this.grid,d=a?0:c[0].length-1,e=a?-1:1;this.gridLayout.startcol+=e;for(var f=0,g=c.length;f<g;f++){var h=c[f],k=h[d].position.clone(),l=h[a?"pop":"shift"]();k.x+=b.w*e;l.moveTo(this.getTileBoundsForGridIndex(f,d),k);h[a?"unshift":"push"](l)}},removeExcessTiles:function(a,b){for(var c,d;this.grid.length>a;){var e=this.grid.pop();c=0;for(d=e.length;c<d;c++){var f=e[c];this.destroyTile(f)}}c=0;for(d=this.grid.length;c<d;c++)for(;this.grid[c].length>
2188 b;)e=this.grid[c],f=e.pop(),this.destroyTile(f)},onMapResize:function(){this.singleTile&&(this.clearGrid(),this.setTileSize())},getTileBounds:function(a){var b=this.maxExtent,c=this.getResolution(),d=c*this.tileSize.w,c=c*this.tileSize.h,e=this.getLonLatFromViewPortPx(a);a=b.left+d*Math.floor((e.lon-b.left)/d);b=b.bottom+c*Math.floor((e.lat-b.bottom)/c);return new OpenLayers.Bounds(a,b,a+d,b+c)},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Format.ArcXML=OpenLayers.Class(OpenLayers.Format.XML,{fontStyleKeys:"antialiasing blockout font fontcolor fontsize fontstyle glowing interval outline printmode shadow transparency".split(" "),request:null,response:null,initialize:function(a){this.request=new OpenLayers.Format.ArcXML.Request;this.response=new OpenLayers.Format.ArcXML.Response;if(a)if("feature"==a.requesttype){this.request.get_image=null;var b=this.request.get_feature.query;this.addCoordSys(b.featurecoordsys,a.featureCoordSys);
2189 this.addCoordSys(b.filtercoordsys,a.filterCoordSys);a.polygon?(b.isspatial=!0,b.spatialfilter.polygon=a.polygon):a.envelope&&(b.isspatial=!0,b.spatialfilter.envelope={minx:0,miny:0,maxx:0,maxy:0},this.parseEnvelope(b.spatialfilter.envelope,a.envelope))}else"image"==a.requesttype?(this.request.get_feature=null,b=this.request.get_image.properties,this.parseEnvelope(b.envelope,a.envelope),this.addLayers(b.layerlist,a.layers),this.addImageSize(b.imagesize,a.tileSize),this.addCoordSys(b.featurecoordsys,
2190 a.featureCoordSys),this.addCoordSys(b.filtercoordsys,a.filterCoordSys)):this.request=null;OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},parseEnvelope:function(a,b){b&&4==b.length&&(a.minx=b[0],a.miny=b[1],a.maxx=b[2],a.maxy=b[3])},addLayers:function(a,b){for(var c=0,d=b.length;c<d;c++)a.push(b[c])},addImageSize:function(a,b){null!==b&&(a.width=b.w,a.height=b.h,a.printwidth=b.w,a.printheight=b.h)},addCoordSys:function(a,b){"string"==typeof b?(a.id=parseInt(b),a.string=b):"object"==typeof b&&
2191 null!==b.proj&&(a.id=b.proj.srsProjNumber,a.string=b.proj.srsCode)},iserror:function(a){var b=null;a?(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]),a=a.documentElement.getElementsByTagName("ERROR"),b=null!==a&&0<a.length):b=""!==this.response.error;return b},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=null;a&&a.documentElement&&(b="ARCXML"==a.documentElement.nodeName?a.documentElement:a.documentElement.getElementsByTagName("ARCXML")[0]);
2192 if(!b||"parsererror"===b.firstChild.nodeName){var c,d;try{c=a.firstChild.nodeValue,d=a.firstChild.childNodes[1].firstChild.nodeValue}catch(e){}throw{message:"Error parsing the ArcXML request",error:c,source:d};}return this.parseResponse(b)},write:function(a){a||(a=this.request);var b=this.createElementNS("","ARCXML");b.setAttribute("version","1.1");var c=this.createElementNS("","REQUEST");if(null!=a.get_image){var d=this.createElementNS("","GET_IMAGE");c.appendChild(d);var e=this.createElementNS("",
2193 "PROPERTIES");d.appendChild(e);a=a.get_image.properties;null!=a.featurecoordsys&&(d=this.createElementNS("","FEATURECOORDSYS"),e.appendChild(d),0===a.featurecoordsys.id?d.setAttribute("string",a.featurecoordsys.string):d.setAttribute("id",a.featurecoordsys.id));null!=a.filtercoordsys&&(d=this.createElementNS("","FILTERCOORDSYS"),e.appendChild(d),0===a.filtercoordsys.id?d.setAttribute("string",a.filtercoordsys.string):d.setAttribute("id",a.filtercoordsys.id));null!=a.envelope&&(d=this.createElementNS("",
2194 "ENVELOPE"),e.appendChild(d),d.setAttribute("minx",a.envelope.minx),d.setAttribute("miny",a.envelope.miny),d.setAttribute("maxx",a.envelope.maxx),d.setAttribute("maxy",a.envelope.maxy));d=this.createElementNS("","IMAGESIZE");e.appendChild(d);d.setAttribute("height",a.imagesize.height);d.setAttribute("width",a.imagesize.width);if(a.imagesize.height!=a.imagesize.printheight||a.imagesize.width!=a.imagesize.printwidth)d.setAttribute("printheight",a.imagesize.printheight),d.setArrtibute("printwidth",a.imagesize.printwidth);
2195 null!=a.background&&(d=this.createElementNS("","BACKGROUND"),e.appendChild(d),d.setAttribute("color",a.background.color.r+","+a.background.color.g+","+a.background.color.b),null!==a.background.transcolor&&d.setAttribute("transcolor",a.background.transcolor.r+","+a.background.transcolor.g+","+a.background.transcolor.b));if(null!=a.layerlist&&0<a.layerlist.length)for(d=this.createElementNS("","LAYERLIST"),e.appendChild(d),e=0;e<a.layerlist.length;e++){var f=this.createElementNS("","LAYERDEF");d.appendChild(f);
2196 f.setAttribute("id",a.layerlist[e].id);f.setAttribute("visible",a.layerlist[e].visible);if("object"==typeof a.layerlist[e].query){var g=a.layerlist[e].query;if(0>g.where.length)continue;var h=null,h="boolean"==typeof g.spatialfilter&&g.spatialfilter?this.createElementNS("","SPATIALQUERY"):this.createElementNS("","QUERY");h.setAttribute("where",g.where);"number"==typeof g.accuracy&&0<g.accuracy&&h.setAttribute("accuracy",g.accuracy);"number"==typeof g.featurelimit&&2E3>g.featurelimit&&h.setAttribute("featurelimit",
2197 g.featurelimit);"string"==typeof g.subfields&&"#ALL#"!=g.subfields&&h.setAttribute("subfields",g.subfields);"string"==typeof g.joinexpression&&0<g.joinexpression.length&&h.setAttribute("joinexpression",g.joinexpression);"string"==typeof g.jointables&&0<g.jointables.length&&h.setAttribute("jointables",g.jointables);f.appendChild(h)}"object"==typeof a.layerlist[e].renderer&&this.addRenderer(f,a.layerlist[e].renderer)}}else null!=a.get_feature&&(d=this.createElementNS("","GET_FEATURES"),d.setAttribute("outputmode",
2198 "newxml"),d.setAttribute("checkesc","true"),a.get_feature.geometry?d.setAttribute("geometry",a.get_feature.geometry):d.setAttribute("geometry","false"),a.get_feature.compact&&d.setAttribute("compact",a.get_feature.compact),"number"==a.get_feature.featurelimit&&d.setAttribute("featurelimit",a.get_feature.featurelimit),d.setAttribute("globalenvelope","true"),c.appendChild(d),null!=a.get_feature.layer&&0<a.get_feature.layer.length&&(e=this.createElementNS("","LAYER"),e.setAttribute("id",a.get_feature.layer),
2199 d.appendChild(e)),a=a.get_feature.query,null!=a&&(e=null,e=a.isspatial?this.createElementNS("","SPATIALQUERY"):this.createElementNS("","QUERY"),d.appendChild(e),"number"==typeof a.accuracy&&e.setAttribute("accuracy",a.accuracy),null!=a.featurecoordsys&&(d=this.createElementNS("","FEATURECOORDSYS"),0==a.featurecoordsys.id?d.setAttribute("string",a.featurecoordsys.string):d.setAttribute("id",a.featurecoordsys.id),e.appendChild(d)),null!=a.filtercoordsys&&(d=this.createElementNS("","FILTERCOORDSYS"),
2200 0===a.filtercoordsys.id?d.setAttribute("string",a.filtercoordsys.string):d.setAttribute("id",a.filtercoordsys.id),e.appendChild(d)),0<a.buffer&&(d=this.createElementNS("","BUFFER"),d.setAttribute("distance",a.buffer),e.appendChild(d)),a.isspatial&&(d=this.createElementNS("","SPATIALFILTER"),d.setAttribute("relation",a.spatialfilter.relation),e.appendChild(d),a.spatialfilter.envelope?(f=this.createElementNS("","ENVELOPE"),f.setAttribute("minx",a.spatialfilter.envelope.minx),f.setAttribute("miny",a.spatialfilter.envelope.miny),
2201 f.setAttribute("maxx",a.spatialfilter.envelope.maxx),f.setAttribute("maxy",a.spatialfilter.envelope.maxy),d.appendChild(f)):"object"==typeof a.spatialfilter.polygon&&d.appendChild(this.writePolygonGeometry(a.spatialfilter.polygon))),null!=a.where&&0<a.where.length&&e.setAttribute("where",a.where)));b.appendChild(c);return OpenLayers.Format.XML.prototype.write.apply(this,[b])},addGroupRenderer:function(a,b){var c=this.createElementNS("","GROUPRENDERER");a.appendChild(c);for(var d=0;d<b.length;d++)this.addRenderer(c,
2202 b[d])},addRenderer:function(a,b){if(OpenLayers.Util.isArray(b))this.addGroupRenderer(a,b);else{var c=this.createElementNS("",b.type.toUpperCase()+"RENDERER");a.appendChild(c);"VALUEMAPRENDERER"==c.tagName?this.addValueMapRenderer(c,b):"VALUEMAPLABELRENDERER"==c.tagName?this.addValueMapLabelRenderer(c,b):"SIMPLELABELRENDERER"==c.tagName?this.addSimpleLabelRenderer(c,b):"SCALEDEPENDENTRENDERER"==c.tagName&&this.addScaleDependentRenderer(c,b)}},addScaleDependentRenderer:function(a,b){"string"!=typeof b.lower&&
2203 "number"!=typeof b.lower||a.setAttribute("lower",b.lower);"string"!=typeof b.upper&&"number"!=typeof b.upper||a.setAttribute("upper",b.upper);this.addRenderer(a,b.renderer)},addValueMapLabelRenderer:function(a,b){a.setAttribute("lookupfield",b.lookupfield);a.setAttribute("labelfield",b.labelfield);if("object"==typeof b.exacts)for(var c=0,d=b.exacts.length;c<d;c++){var e=b.exacts[c],f=this.createElementNS("","EXACT");"string"==typeof e.value&&f.setAttribute("value",e.value);"string"==typeof e.label&&
2204 f.setAttribute("label",e.label);"string"==typeof e.method&&f.setAttribute("method",e.method);a.appendChild(f);if("object"==typeof e.symbol){var g=null;"text"==e.symbol.type&&(g=this.createElementNS("","TEXTSYMBOL"));if(null!=g){for(var h=this.fontStyleKeys,k=0,l=h.length;k<l;k++){var m=h[k];e.symbol[m]&&g.setAttribute(m,e.symbol[m])}f.appendChild(g)}}}},addValueMapRenderer:function(a,b){a.setAttribute("lookupfield",b.lookupfield);if("object"==typeof b.ranges)for(var c=0,d=b.ranges.length;c<d;c++){var e=
2205 b.ranges[c],f=this.createElementNS("","RANGE");f.setAttribute("lower",e.lower);f.setAttribute("upper",e.upper);a.appendChild(f);if("object"==typeof e.symbol){var g=null;"simplepolygon"==e.symbol.type&&(g=this.createElementNS("","SIMPLEPOLYGONSYMBOL"));null!=g&&("string"==typeof e.symbol.boundarycolor&&g.setAttribute("boundarycolor",e.symbol.boundarycolor),"string"==typeof e.symbol.fillcolor&&g.setAttribute("fillcolor",e.symbol.fillcolor),"number"==typeof e.symbol.filltransparency&&g.setAttribute("filltransparency",
2206 e.symbol.filltransparency),f.appendChild(g))}}else if("object"==typeof b.exacts)for(c=0,d=b.exacts.length;c<d;c++)e=b.exacts[c],f=this.createElementNS("","EXACT"),"string"==typeof e.value&&f.setAttribute("value",e.value),"string"==typeof e.label&&f.setAttribute("label",e.label),"string"==typeof e.method&&f.setAttribute("method",e.method),a.appendChild(f),"object"==typeof e.symbol&&(g=null,"simplemarker"==e.symbol.type&&(g=this.createElementNS("","SIMPLEMARKERSYMBOL")),null!=g&&("string"==typeof e.symbol.antialiasing&&
2207 g.setAttribute("antialiasing",e.symbol.antialiasing),"string"==typeof e.symbol.color&&g.setAttribute("color",e.symbol.color),"string"==typeof e.symbol.outline&&g.setAttribute("outline",e.symbol.outline),"string"==typeof e.symbol.overlap&&g.setAttribute("overlap",e.symbol.overlap),"string"==typeof e.symbol.shadow&&g.setAttribute("shadow",e.symbol.shadow),"number"==typeof e.symbol.transparency&&g.setAttribute("transparency",e.symbol.transparency),"string"==typeof e.symbol.usecentroid&&g.setAttribute("usecentroid",
2208 e.symbol.usecentroid),"number"==typeof e.symbol.width&&g.setAttribute("width",e.symbol.width),f.appendChild(g)))},addSimpleLabelRenderer:function(a,b){a.setAttribute("field",b.field);for(var c="featureweight howmanylabels labelbufferratio labelpriorities labelweight linelabelposition rotationalangles".split(" "),d=0,e=c.length;d<e;d++){var f=c[d];b[f]&&a.setAttribute(f,b[f])}if("text"==b.symbol.type){var g=b.symbol,h=this.createElementNS("","TEXTSYMBOL");a.appendChild(h);c=this.fontStyleKeys;d=0;
2209 for(e=c.length;d<e;d++)f=c[d],g[f]&&h.setAttribute(f,b[f])}},writePolygonGeometry:function(a){if(!(a instanceof OpenLayers.Geometry.Polygon))throw{message:"Cannot write polygon geometry to ArcXML with an "+a.CLASS_NAME+" object.",geometry:a};for(var b=this.createElementNS("","POLYGON"),c=0,d=a.components.length;c<d;c++){for(var e=a.components[c],f=this.createElementNS("","RING"),g=0,h=e.components.length;g<h;g++){var k=e.components[g],l=this.createElementNS("","POINT");l.setAttribute("x",k.x);l.setAttribute("y",
2210 k.y);f.appendChild(l)}b.appendChild(f)}return b},parseResponse:function(a){"string"==typeof a&&(a=(new OpenLayers.Format.XML).read(a));var b=new OpenLayers.Format.ArcXML.Response,c=a.getElementsByTagName("ERROR");if(null!=c&&0<c.length)b.error=this.getChildValue(c,"Unknown error.");else{c=a.getElementsByTagName("RESPONSE");if(null==c||0==c.length)return b.error="No RESPONSE tag found in ArcXML response.",b;var d=c[0].firstChild.nodeName;"#text"==d&&(d=c[0].firstChild.nextSibling.nodeName);if("IMAGE"==
2211 d)c=a.getElementsByTagName("ENVELOPE"),a=a.getElementsByTagName("OUTPUT"),null==c||0==c.length?b.error="No ENVELOPE tag found in ArcXML response.":null==a||0==a.length?b.error="No OUTPUT tag found in ArcXML response.":(c=this.parseAttributes(c[0]),d=this.parseAttributes(a[0]),b.image="string"==typeof d.type?{envelope:c,output:{type:d.type,data:this.getChildValue(a[0])}}:{envelope:c,output:d});else if("FEATURES"==d){if(a=c[0].getElementsByTagName("FEATURES"),c=a[0].getElementsByTagName("FEATURECOUNT"),
2212 b.features.featurecount=c[0].getAttribute("count"),0<b.features.featurecount)for(c=a[0].getElementsByTagName("ENVELOPE"),b.features.envelope=this.parseAttributes(c[0],"number"),a=a[0].getElementsByTagName("FEATURE"),c=0;c<a.length;c++){for(var d=new OpenLayers.Feature.Vector,e=a[c].getElementsByTagName("FIELD"),f=0;f<e.length;f++){var g=e[f].getAttribute("name"),h=e[f].getAttribute("value");d.attributes[g]=h}e=a[c].getElementsByTagName("POLYGON");if(0<e.length){e=e[0].getElementsByTagName("RING");
2213 f=[];for(g=0;g<e.length;g++){h=[];h.push(this.parsePointGeometry(e[g]));for(var k=e[g].getElementsByTagName("HOLE"),l=0;l<k.length;l++)h.push(this.parsePointGeometry(k[l]));f.push(new OpenLayers.Geometry.Polygon(h))}d.geometry=1==f.length?f[0]:new OpenLayers.Geometry.MultiPolygon(f)}b.features.feature.push(d)}}else b.error="Unidentified response type."}return b},parseAttributes:function(a,b){for(var c={},d=0;d<a.attributes.length;d++)c[a.attributes[d].nodeName]="number"==b?parseFloat(a.attributes[d].nodeValue):
2214 a.attributes[d].nodeValue;return c},parsePointGeometry:function(a){var b=[],c=a.getElementsByTagName("COORDS");if(0<c.length)for(a=this.getChildValue(c[0]),a=a.split(/;/),c=0;c<a.length;c++){var d=a[c].split(/ /);b.push(new OpenLayers.Geometry.Point(d[0],d[1]))}else if(a=a.getElementsByTagName("POINT"),0<a.length)for(c=0;c<a.length;c++)b.push(new OpenLayers.Geometry.Point(parseFloat(a[c].getAttribute("x")),parseFloat(a[c].getAttribute("y"))));return new OpenLayers.Geometry.LinearRing(b)},CLASS_NAME:"OpenLayers.Format.ArcXML"});
2215 OpenLayers.Format.ArcXML.Request=OpenLayers.Class({initialize:function(a){return OpenLayers.Util.extend(this,{get_image:{properties:{background:null,draw:!0,envelope:{minx:0,miny:0,maxx:0,maxy:0},featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},imagesize:{height:0,width:0,dpi:96,printheight:0,printwidth:0,scalesymbols:!1},layerlist:[],output:{baseurl:"",legendbaseurl:"",legendname:"",legendpath:"",
2216 legendurl:"",name:"",path:"",type:"jpg",url:""}}},get_feature:{layer:"",query:{isspatial:!1,featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},buffer:0,where:"",spatialfilter:{relation:"envelope_intersection",envelope:null}}},environment:{separators:{cs:" ",ts:";"}},layer:[],workspaces:[]})},CLASS_NAME:"OpenLayers.Format.ArcXML.Request"});
2217 OpenLayers.Format.ArcXML.Response=OpenLayers.Class({initialize:function(a){return OpenLayers.Util.extend(this,{image:{envelope:null,output:""},features:{featurecount:0,envelope:null,feature:[]},error:""})},CLASS_NAME:"OpenLayers.Format.ArcXML.Response"});(function(){function a(){this._object=f&&!k?new f:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[]}function b(){return new a}function c(a){b.onreadystatechange&&b.onreadystatechange.apply(a);a.dispatchEvent({type:"readystatechange",bubbles:!1,cancelable:!1,timeStamp:new Date+0})}function d(a){try{a.responseText=a._object.responseText}catch(b){}try{var c;var d=a._object,e=d.responseXML,f=d.responseText;h&&(f&&e&&!e.documentElement&&d.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/))&&
2218 (e=new window.ActiveXObject("Microsoft.XMLDOM"),e.async=!1,e.validateOnParse=!1,e.loadXML(f));c=e&&(h&&0!=e.parseError||!e.documentElement||e.documentElement&&"parsererror"==e.documentElement.tagName)?null:e;a.responseXML=c}catch(g){}try{a.status=a._object.status}catch(k){}try{a.statusText=a._object.statusText}catch(u){}}function e(a){a._object.onreadystatechange=new window.Function}var f=window.XMLHttpRequest,g=!!window.controllers,h=window.document.all&&!window.opera,k=h&&window.navigator.userAgent.match(/MSIE 7.0/);
2219 b.prototype=a.prototype;g&&f.wrapped&&(b.wrapped=f.wrapped);b.UNSENT=0;b.OPENED=1;b.HEADERS_RECEIVED=2;b.LOADING=3;b.DONE=4;b.prototype.readyState=b.UNSENT;b.prototype.responseText="";b.prototype.responseXML=null;b.prototype.status=0;b.prototype.statusText="";b.prototype.priority="NORMAL";b.prototype.onreadystatechange=null;b.onreadystatechange=null;b.onopen=null;b.onsend=null;b.onabort=null;b.prototype.open=function(a,f,k,p,q){delete this._headers;3>arguments.length&&(k=!0);this._async=k;var r=this,
2220 s=this.readyState,t;h&&k&&(t=function(){s!=b.DONE&&(e(r),r.abort())},window.attachEvent("onunload",t));b.onopen&&b.onopen.apply(this,arguments);4<arguments.length?this._object.open(a,f,k,p,q):3<arguments.length?this._object.open(a,f,k,p):this._object.open(a,f,k);this.readyState=b.OPENED;c(this);this._object.onreadystatechange=function(){if(!g||k)r.readyState=r._object.readyState,d(r),r._aborted?r.readyState=b.UNSENT:(r.readyState==b.DONE&&(delete r._data,e(r),h&&k&&window.detachEvent("onunload",t)),
2221 s!=r.readyState&&c(r),s=r.readyState)}};b.prototype.send=function(a){b.onsend&&b.onsend.apply(this,arguments);arguments.length||(a=null);a&&a.nodeType&&(a=window.XMLSerializer?(new window.XMLSerializer).serializeToString(a):a.xml,this._headers["Content-Type"]||this._object.setRequestHeader("Content-Type","application/xml"));this._data=a;a:if(this._object.send(this._data),g&&!this._async)for(this.readyState=b.OPENED,d(this);this.readyState<b.DONE;)if(this.readyState++,c(this),this._aborted)break a};
2222 b.prototype.abort=function(){b.onabort&&b.onabort.apply(this,arguments);this.readyState>b.UNSENT&&(this._aborted=!0);this._object.abort();e(this);this.readyState=b.UNSENT;delete this._data};b.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()};b.prototype.getResponseHeader=function(a){return this._object.getResponseHeader(a)};b.prototype.setRequestHeader=function(a,b){this._headers||(this._headers={});this._headers[a]=b;return this._object.setRequestHeader(a,b)};
2223 b.prototype.addEventListener=function(a,b,c){for(var d=0,e;e=this._listeners[d];d++)if(e[0]==a&&e[1]==b&&e[2]==c)return;this._listeners.push([a,b,c])};b.prototype.removeEventListener=function(a,b,c){for(var d=0,e;(e=this._listeners[d])&&(e[0]!=a||e[1]!=b||e[2]!=c);d++);e&&this._listeners.splice(d,1)};b.prototype.dispatchEvent=function(a){a={type:a.type,target:this,currentTarget:this,eventPhase:2,bubbles:a.bubbles,cancelable:a.cancelable,timeStamp:a.timeStamp,stopPropagation:function(){},preventDefault:function(){},
2224 initEvent:function(){}};"readystatechange"==a.type&&this.onreadystatechange&&(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[a]);for(var b=0,c;c=this._listeners[b];b++)c[0]!=a.type||c[2]||(c[1].handleEvent||c[1]).apply(this,[a])};b.prototype.toString=function(){return"[object XMLHttpRequest]"};b.toString=function(){return"[XMLHttpRequest]"};window.Function.prototype.apply||(window.Function.prototype.apply=function(a,b){b||(b=[]);a.__func=this;a.__func(b[0],b[1],b[2],b[3],
2225 b[4]);delete a.__func});OpenLayers.Request||(OpenLayers.Request={});OpenLayers.Request.XMLHttpRequest=b})();OpenLayers.ProxyHost="";OpenLayers.Request||(OpenLayers.Request={});
2226 OpenLayers.Util.extend(OpenLayers.Request,{DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:!0,user:void 0,password:void 0,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},URL_SPLIT_REGEX:/([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,events:new OpenLayers.Events(this),makeSameOrigin:function(a,b){var c=0!==a.indexOf("http"),d=!c&&a.match(this.URL_SPLIT_REGEX);if(d){var e=window.location,c=d[1]==e.protocol&&d[3]==
2227 e.hostname,d=d[4],e=e.port;if(80!=d&&""!=d||"80"!=e&&""!=e)c=c&&d==e}c||b&&(a="function"==typeof b?b(a):b+encodeURIComponent(a));return a},issue:function(a){var b=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});a=a||{};a.headers=a.headers||{};a=OpenLayers.Util.applyDefaults(a,b);a.headers=OpenLayers.Util.applyDefaults(a.headers,b.headers);var b=!1,c;for(c in a.headers)a.headers.hasOwnProperty(c)&&"x-requested-with"===c.toLowerCase()&&(b=!0);!1===b&&(a.headers["X-Requested-With"]=
2228 "XMLHttpRequest");var d=new OpenLayers.Request.XMLHttpRequest,e=OpenLayers.Util.urlAppend(a.url,OpenLayers.Util.getParameterString(a.params||{})),e=OpenLayers.Request.makeSameOrigin(e,a.proxy);d.open(a.method,e,a.async,a.user,a.password);for(var f in a.headers)d.setRequestHeader(f,a.headers[f]);var g=this.events,h=this;d.onreadystatechange=function(){d.readyState==OpenLayers.Request.XMLHttpRequest.DONE&&!1!==g.triggerEvent("complete",{request:d,config:a,requestUrl:e})&&h.runCallbacks({request:d,config:a,
2229 requestUrl:e})};!1===a.async?d.send(a.data):window.setTimeout(function(){0!==d.readyState&&d.send(a.data)},0);return d},runCallbacks:function(a){var b=a.request,c=a.config,d=c.scope?OpenLayers.Function.bind(c.callback,c.scope):c.callback,e;c.success&&(e=c.scope?OpenLayers.Function.bind(c.success,c.scope):c.success);var f;c.failure&&(f=c.scope?OpenLayers.Function.bind(c.failure,c.scope):c.failure);"file:"==OpenLayers.Util.createUrlObject(c.url).protocol&&b.responseText&&(b.status=200);d(b);if(!b.status||
2230 200<=b.status&&300>b.status)this.events.triggerEvent("success",a),e&&e(b);b.status&&(200>b.status||300<=b.status)&&(this.events.triggerEvent("failure",a),f&&f(b))},GET:function(a){a=OpenLayers.Util.extend(a,{method:"GET"});return OpenLayers.Request.issue(a)},POST:function(a){a=OpenLayers.Util.extend(a,{method:"POST"});a.headers=a.headers?a.headers:{};"CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(a.headers)||(a.headers["Content-Type"]="application/xml");return OpenLayers.Request.issue(a)},PUT:function(a){a=
2231 OpenLayers.Util.extend(a,{method:"PUT"});a.headers=a.headers?a.headers:{};"CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(a.headers)||(a.headers["Content-Type"]="application/xml");return OpenLayers.Request.issue(a)},DELETE:function(a){a=OpenLayers.Util.extend(a,{method:"DELETE"});return OpenLayers.Request.issue(a)},HEAD:function(a){a=OpenLayers.Util.extend(a,{method:"HEAD"});return OpenLayers.Request.issue(a)},OPTIONS:function(a){a=OpenLayers.Util.extend(a,{method:"OPTIONS"});return OpenLayers.Request.issue(a)}});OpenLayers.Layer.ArcIMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{ClientVersion:"9.2",ServiceName:""},featureCoordSys:"4326",filterCoordSys:"4326",layers:null,async:!0,name:"ArcIMS",isBaseLayer:!0,DEFAULT_OPTIONS:{tileSize:new OpenLayers.Size(512,512),featureCoordSys:"4326",filterCoordSys:"4326",layers:null,isBaseLayer:!0,async:!0,name:"ArcIMS"},initialize:function(a,b,c){this.tileSize=new OpenLayers.Size(512,512);this.params=OpenLayers.Util.applyDefaults({ServiceName:c.serviceName},
2232 this.DEFAULT_PARAMS);this.options=OpenLayers.Util.applyDefaults(c,this.DEFAULT_OPTIONS);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a,b,this.params,c]);this.transparent&&(this.isBaseLayer||(this.isBaseLayer=!1),"image/jpeg"==this.format&&(this.format=OpenLayers.Util.alphaHack()?"image/gif":"image/png"));null===this.options.layers&&(this.options.layers=[])},getURL:function(a){var b="";a=this.adjustBounds(a);a=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",
2233 envelope:a.toArray(),tileSize:this.tileSize}));a=new OpenLayers.Request.POST({url:this.getFullRequestString(),data:a.write(),async:!1});null!=a&&(b=a.responseXML,b&&b.documentElement||(b=a.responseText),b=(new OpenLayers.Format.ArcXML).read(b),b=this.getUrlOrImage(b.image.output));return b},getURLasync:function(a,b,c){a=this.adjustBounds(a);a=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:a.toArray(),tileSize:this.tileSize}));OpenLayers.Request.POST({url:this.getFullRequestString(),
2234 async:!0,data:a.write(),callback:function(a){var e=a.responseXML;e&&e.documentElement||(e=a.responseText);a=(new OpenLayers.Format.ArcXML).read(e);b.call(c,this.getUrlOrImage(a.image.output))},scope:this})},getUrlOrImage:function(a){var b="";a.url?b=a.url:a.data&&(b="data:image/"+a.type+";base64,"+a.data);return b},setLayerQuery:function(a,b){for(var c=0;c<this.options.layers.length;c++)if(a==this.options.layers[c].id){this.options.layers[c].query=b;return}this.options.layers.push({id:a,visible:!0,
2235 query:b})},getFeatureInfo:function(a,b,c){var d=c.buffer||1,e=c.callback||function(){},f=c.scope||window,g={};OpenLayers.Util.extend(g,this.options);g.requesttype="feature";a instanceof OpenLayers.LonLat?(g.polygon=null,g.envelope=[a.lon-d,a.lat-d,a.lon+d,a.lat+d]):a instanceof OpenLayers.Geometry.Polygon&&(g.envelope=null,g.polygon=a);var h=new OpenLayers.Format.ArcXML(g);OpenLayers.Util.extend(h.request.get_feature,c);h.request.get_feature.layer=b.id;"number"==typeof b.query.accuracy?h.request.get_feature.query.accuracy=
2236 b.query.accuracy:(a=this.map.getCenter(),c=this.map.getViewPortPxFromLonLat(a),c.x++,c=this.map.getLonLatFromPixel(c),h.request.get_feature.query.accuracy=c.lon-a.lon);h.request.get_feature.query.where=b.query.where;h.request.get_feature.query.spatialfilter.relation="area_intersection";OpenLayers.Request.POST({url:this.getFullRequestString({CustomService:"Query"}),data:h.write(),callback:function(a){a=h.parseResponse(a.responseText);h.iserror()?e.call(f,null):e.call(f,a.features)}})},clone:function(a){null==
2237 a&&(a=new OpenLayers.Layer.ArcIMS(this.name,this.url,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},CLASS_NAME:"OpenLayers.Layer.ArcIMS"});OpenLayers.Control.PanZoom=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,buttons:null,position:null,initialize:function(a){this.position=new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,OpenLayers.Control.PanZoom.Y);OpenLayers.Control.prototype.initialize.apply(this,arguments)},destroy:function(){this.map&&this.map.events.unregister("buttonclick",this,this.onButtonClick);this.removeButtons();this.position=this.buttons=null;OpenLayers.Control.prototype.destroy.apply(this,arguments)},
2238 setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.register("buttonclick",this,this.onButtonClick)},draw:function(a){OpenLayers.Control.prototype.draw.apply(this,arguments);a=this.position;this.buttons=[];var b={w:18,h:18},c=new OpenLayers.Pixel(a.x+b.w/2,a.y);this._addButton("panup","north-mini.png",c,b);a.y=c.y+b.h;this._addButton("panleft","west-mini.png",a,b);this._addButton("panright","east-mini.png",a.add(b.w,0),b);this._addButton("pandown","south-mini.png",
2239 c.add(0,2*b.h),b);this._addButton("zoomin","zoom-plus-mini.png",c.add(0,3*b.h+5),b);this._addButton("zoomworld","zoom-world-mini.png",c.add(0,4*b.h+5),b);this._addButton("zoomout","zoom-minus-mini.png",c.add(0,5*b.h+5),b);return this.div},_addButton:function(a,b,c,d){b=OpenLayers.Util.getImageLocation(b);c=OpenLayers.Util.createAlphaImageDiv(this.id+"_"+a,c,d,b,"absolute");c.style.cursor="pointer";this.div.appendChild(c);c.action=a;c.className="olButton";this.buttons.push(c);return c},_removeButton:function(a){this.div.removeChild(a);
2240 OpenLayers.Util.removeItem(this.buttons,a)},removeButtons:function(){for(var a=this.buttons.length-1;0<=a;--a)this._removeButton(this.buttons[a])},onButtonClick:function(a){switch(a.buttonElement.action){case "panup":this.map.pan(0,-this.getSlideFactor("h"));break;case "pandown":this.map.pan(0,this.getSlideFactor("h"));break;case "panleft":this.map.pan(-this.getSlideFactor("w"),0);break;case "panright":this.map.pan(this.getSlideFactor("w"),0);break;case "zoomin":this.map.zoomIn();break;case "zoomout":this.map.zoomOut();
2241 break;case "zoomworld":this.map.zoomToMaxExtent()}},getSlideFactor:function(a){return this.slideRatio?this.map.getSize()[a]*this.slideRatio:this.slideFactor},CLASS_NAME:"OpenLayers.Control.PanZoom"});OpenLayers.Control.PanZoom.X=4;OpenLayers.Control.PanZoom.Y=4;OpenLayers.Control.PanZoomBar=OpenLayers.Class(OpenLayers.Control.PanZoom,{zoomStopWidth:18,zoomStopHeight:11,slider:null,sliderEvents:null,zoombarDiv:null,zoomWorldIcon:!1,panIcons:!0,forceFixedZoomLevel:!1,mouseDragStart:null,deltaY:null,zoomStart:null,destroy:function(){this._removeZoomBar();this.map.events.un({changebaselayer:this.redraw,updatesize:this.redraw,scope:this});OpenLayers.Control.PanZoom.prototype.destroy.apply(this,arguments);delete this.mouseDragStart;delete this.zoomStart},setMap:function(a){OpenLayers.Control.PanZoom.prototype.setMap.apply(this,
2242 arguments);this.map.events.on({changebaselayer:this.redraw,updatesize:this.redraw,scope:this})},redraw:function(){null!=this.div&&(this.removeButtons(),this._removeZoomBar());this.draw()},draw:function(a){OpenLayers.Control.prototype.draw.apply(this,arguments);a=this.position.clone();this.buttons=[];var b={w:18,h:18};if(this.panIcons){var c=new OpenLayers.Pixel(a.x+b.w/2,a.y),d=b.w;this.zoomWorldIcon&&(c=new OpenLayers.Pixel(a.x+b.w,a.y));this._addButton("panup","north-mini.png",c,b);a.y=c.y+b.h;
2243 this._addButton("panleft","west-mini.png",a,b);this.zoomWorldIcon&&(this._addButton("zoomworld","zoom-world-mini.png",a.add(b.w,0),b),d*=2);this._addButton("panright","east-mini.png",a.add(d,0),b);this._addButton("pandown","south-mini.png",c.add(0,2*b.h),b);this._addButton("zoomin","zoom-plus-mini.png",c.add(0,3*b.h+5),b);c=this._addZoomBar(c.add(0,4*b.h+5));this._addButton("zoomout","zoom-minus-mini.png",c,b)}else this._addButton("zoomin","zoom-plus-mini.png",a,b),c=this._addZoomBar(a.add(0,b.h)),
2244 this._addButton("zoomout","zoom-minus-mini.png",c,b),this.zoomWorldIcon&&(c=c.add(0,b.h+3),this._addButton("zoomworld","zoom-world-mini.png",c,b));return this.div},_addZoomBar:function(a){var b=OpenLayers.Util.getImageLocation("slider.png"),c=this.id+"_"+this.map.id,d=this.map.getMinZoom(),e=this.map.getNumZoomLevels()-1-this.map.getZoom(),e=OpenLayers.Util.createAlphaImageDiv(c,a.add(-1,e*this.zoomStopHeight),{w:20,h:9},b,"absolute");e.style.cursor="move";this.slider=e;this.sliderEvents=new OpenLayers.Events(this,
2245 e,null,!0,{includeXY:!0});this.sliderEvents.on({touchstart:this.zoomBarDown,touchmove:this.zoomBarDrag,touchend:this.zoomBarUp,mousedown:this.zoomBarDown,mousemove:this.zoomBarDrag,mouseup:this.zoomBarUp});var f={w:this.zoomStopWidth,h:this.zoomStopHeight*(this.map.getNumZoomLevels()-d)},b=OpenLayers.Util.getImageLocation("zoombar.png"),c=null;OpenLayers.Util.alphaHack()?(c=this.id+"_"+this.map.id,c=OpenLayers.Util.createAlphaImageDiv(c,a,{w:f.w,h:this.zoomStopHeight},b,"absolute",null,"crop"),c.style.height=
2246 f.h+"px"):c=OpenLayers.Util.createDiv("OpenLayers_Control_PanZoomBar_Zoombar"+this.map.id,a,f,b);c.style.cursor="pointer";c.className="olButton";this.zoombarDiv=c;this.div.appendChild(c);this.startTop=parseInt(c.style.top);this.div.appendChild(e);this.map.events.register("zoomend",this,this.moveZoomBar);return a=a.add(0,this.zoomStopHeight*(this.map.getNumZoomLevels()-d))},_removeZoomBar:function(){this.sliderEvents.un({touchstart:this.zoomBarDown,touchmove:this.zoomBarDrag,touchend:this.zoomBarUp,
2247 mousedown:this.zoomBarDown,mousemove:this.zoomBarDrag,mouseup:this.zoomBarUp});this.sliderEvents.destroy();this.div.removeChild(this.zoombarDiv);this.zoombarDiv=null;this.div.removeChild(this.slider);this.slider=null;this.map.events.unregister("zoomend",this,this.moveZoomBar)},onButtonClick:function(a){OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this,arguments);if(a.buttonElement===this.zoombarDiv){var b=a.buttonXY.y/this.zoomStopHeight;if(this.forceFixedZoomLevel||!this.map.fractionalZoom)b=
2248 Math.floor(b);b=this.map.getNumZoomLevels()-1-b;b=Math.min(Math.max(b,0),this.map.getNumZoomLevels()-1);this.map.zoomTo(b)}},passEventToSlider:function(a){this.sliderEvents.handleBrowserEvent(a)},zoomBarDown:function(a){if(OpenLayers.Event.isLeftClick(a)||OpenLayers.Event.isSingleTouch(a))this.map.events.on({touchmove:this.passEventToSlider,mousemove:this.passEventToSlider,mouseup:this.passEventToSlider,scope:this}),this.mouseDragStart=a.xy.clone(),this.zoomStart=a.xy.clone(),this.div.style.cursor=
2249 "move",this.zoombarDiv.offsets=null,OpenLayers.Event.stop(a)},zoomBarDrag:function(a){if(null!=this.mouseDragStart){var b=this.mouseDragStart.y-a.xy.y,c=OpenLayers.Util.pagePosition(this.zoombarDiv);0<a.clientY-c[1]&&a.clientY-c[1]<parseInt(this.zoombarDiv.style.height)-2&&(b=parseInt(this.slider.style.top)-b,this.slider.style.top=b+"px",this.mouseDragStart=a.xy.clone());this.deltaY=this.zoomStart.y-a.xy.y;OpenLayers.Event.stop(a)}},zoomBarUp:function(a){if((OpenLayers.Event.isLeftClick(a)||"touchend"===
2250 a.type)&&this.mouseDragStart){this.div.style.cursor="";this.map.events.un({touchmove:this.passEventToSlider,mouseup:this.passEventToSlider,mousemove:this.passEventToSlider,scope:this});var b=this.map.zoom;!this.forceFixedZoomLevel&&this.map.fractionalZoom?(b+=this.deltaY/this.zoomStopHeight,b=Math.min(Math.max(b,0),this.map.getNumZoomLevels()-1)):(b+=this.deltaY/this.zoomStopHeight,b=Math.max(Math.round(b),0));this.map.zoomTo(b);this.zoomStart=this.mouseDragStart=null;this.deltaY=0;OpenLayers.Event.stop(a)}},
2251 moveZoomBar:function(){var a=(this.map.getNumZoomLevels()-1-this.map.getZoom())*this.zoomStopHeight+this.startTop+1;this.slider.style.top=a+"px"},CLASS_NAME:"OpenLayers.Control.PanZoomBar"});OpenLayers.Format.WFSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.0",CLASS_NAME:"OpenLayers.Format.WFSCapabilities"});OpenLayers.Format.WFSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{wfs:"http://www.opengis.net/wfs",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",ows:"http://www.opengis.net/ows"},errorProperty:"featureTypeList",defaultPrefix:"wfs",read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},readers:{wfs:{WFS_Capabilities:function(a,
2252 b){this.readChildNodes(a,b)},FeatureTypeList:function(a,b){b.featureTypeList={featureTypes:[]};this.readChildNodes(a,b.featureTypeList)},FeatureType:function(a,b){var c={};this.readChildNodes(a,c);b.featureTypes.push(c)},Name:function(a,b){var c=this.getChildValue(a);c&&(c=c.split(":"),b.name=c.pop(),0<c.length&&(b.featureNS=this.lookupNamespaceURI(a,c[0])))},Title:function(a,b){var c=this.getChildValue(a);c&&(b.title=c)},Abstract:function(a,b){var c=this.getChildValue(a);c&&(b["abstract"]=c)}}},
2253 CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1"});OpenLayers.Format.WFSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},readers:{wfs:OpenLayers.Util.applyDefaults({DefaultSRS:function(a,b){var c=this.getChildValue(a);c&&(b.srs=c)}},OpenLayers.Format.WFSCapabilities.v1.prototype.readers.wfs),ows:OpenLayers.Format.OWSCommon.v1.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_1_0"});OpenLayers.Layer.Image=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:!0,url:null,extent:null,size:null,tile:null,aspectRatio:null,initialize:function(a,b,c,d,e){this.url=b;this.maxExtent=this.extent=c;this.size=d;OpenLayers.Layer.prototype.initialize.apply(this,[a,e]);this.aspectRatio=this.extent.getHeight()/this.size.h/(this.extent.getWidth()/this.size.w)},destroy:function(){this.tile&&(this.removeTileMonitoringHooks(this.tile),this.tile.destroy(),this.tile=null);OpenLayers.Layer.prototype.destroy.apply(this,
2254 arguments)},clone:function(a){null==a&&(a=new OpenLayers.Layer.Image(this.name,this.url,this.extent,this.size,this.getOptions()));return a=OpenLayers.Layer.prototype.clone.apply(this,[a])},setMap:function(a){null==this.options.maxResolution&&(this.options.maxResolution=this.aspectRatio*this.extent.getWidth()/this.size.w);OpenLayers.Layer.prototype.setMap.apply(this,arguments)},moveTo:function(a,b,c){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var d=null==this.tile;if(b||d){this.setTileSize();
2255 var e=this.map.getLayerPxFromLonLat({lon:this.extent.left,lat:this.extent.top});d?(this.tile=new OpenLayers.Tile.Image(this,e,this.extent,null,this.tileSize),this.addTileMonitoringHooks(this.tile)):(this.tile.size=this.tileSize.clone(),this.tile.position=e.clone());this.tile.draw()}},setTileSize:function(){var a=this.extent.getWidth()/this.map.getResolution(),b=this.extent.getHeight()/this.map.getResolution();this.tileSize=new OpenLayers.Size(a,b)},addTileMonitoringHooks:function(a){a.onLoadStart=
2256 function(){this.events.triggerEvent("loadstart")};a.events.register("loadstart",this,a.onLoadStart);a.onLoadEnd=function(){this.events.triggerEvent("loadend")};a.events.register("loadend",this,a.onLoadEnd);a.events.register("unload",this,a.onLoadEnd)},removeTileMonitoringHooks:function(a){a.unload();a.events.un({loadstart:a.onLoadStart,loadend:a.onLoadEnd,unload:a.onLoadEnd,scope:this})},setUrl:function(a){this.url=a;this.tile.draw()},getURL:function(a){return this.url},CLASS_NAME:"OpenLayers.Layer.Image"});OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:!0,autoDestroy:!0,initialize:function(a){OpenLayers.Util.extend(this,a);this.options=a;this.active=!1},destroy:function(){this.deactivate();this.options=this.layer=null},setLayer:function(a){this.layer=a},activate:function(){return this.active?!1:this.active=!0},deactivate:function(){return this.active?(this.active=!1,!0):!1},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Strategy.Save=OpenLayers.Class(OpenLayers.Strategy,{events:null,auto:!1,timer:null,initialize:function(a){OpenLayers.Strategy.prototype.initialize.apply(this,[a]);this.events=new OpenLayers.Events(this)},activate:function(){var a=OpenLayers.Strategy.prototype.activate.call(this);if(a&&this.auto)if("number"===typeof this.auto)this.timer=window.setInterval(OpenLayers.Function.bind(this.save,this),1E3*this.auto);else this.layer.events.on({featureadded:this.triggerSave,afterfeaturemodified:this.triggerSave,
2257 scope:this});return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&this.auto&&("number"===typeof this.auto?window.clearInterval(this.timer):this.layer.events.un({featureadded:this.triggerSave,afterfeaturemodified:this.triggerSave,scope:this}));return a},triggerSave:function(a){var b=a.feature;b.state!==OpenLayers.State.INSERT&&b.state!==OpenLayers.State.UPDATE&&b.state!==OpenLayers.State.DELETE||this.save([a.feature])},save:function(a){a||(a=this.layer.features);
2258 this.events.triggerEvent("start",{features:a});var b=this.layer.projection,c=this.layer.map.getProjectionObject();if(!c.equals(b)){for(var d=a.length,e=Array(d),f,g,h=0;h<d;++h)f=a[h],g=f.clone(),g.fid=f.fid,g.state=f.state,f.url&&(g.url=f.url),g._original=f,g.geometry.transform(c,b),e[h]=g;a=e}this.layer.protocol.commit(a,{callback:this.onCommit,scope:this})},onCommit:function(a){var b={response:a};if(a.success()){for(var c=a.reqFeatures,d,e=[],f=a.insertIds||[],g=0,h=0,k=c.length;h<k;++h)if(d=c[h],
2259 d=d._original||d,a=d.state)a==OpenLayers.State.DELETE?e.push(d):a==OpenLayers.State.INSERT&&(d.fid=f[g],++g),d.state=null;0<e.length&&this.layer.destroyFeatures(e);this.events.triggerEvent("success",b)}else this.events.triggerEvent("fail",b)},CLASS_NAME:"OpenLayers.Strategy.Save"});OpenLayers.Events.featureclick=OpenLayers.Class({cache:null,map:null,provides:["featureclick","nofeatureclick","featureover","featureout"],initialize:function(a){this.target=a;if(a.object instanceof OpenLayers.Map)this.setMap(a.object);else if(a.object instanceof OpenLayers.Layer.Vector)a.object.map?this.setMap(a.object.map):a.object.events.register("added",this,function(b){this.setMap(a.object.map)});else throw"Listeners for '"+this.provides.join("', '")+"' events can only be registered for OpenLayers.Layer.Vector or OpenLayers.Map instances";
2260 for(var b=this.provides.length-1;0<=b;--b)a.extensions[this.provides[b]]=!0},setMap:function(a){this.map=a;this.cache={};a.events.register("mousedown",this,this.start,{extension:!0});a.events.register("mouseup",this,this.onClick,{extension:!0});a.events.register("touchstart",this,this.start,{extension:!0});a.events.register("touchmove",this,this.cancel,{extension:!0});a.events.register("touchend",this,this.onClick,{extension:!0});a.events.register("mousemove",this,this.onMousemove,{extension:!0})},
2261 start:function(a){this.startEvt=a},cancel:function(a){delete this.startEvt},onClick:function(a){if(this.startEvt&&("touchend"===a.type||OpenLayers.Event.isLeftClick(a))){a=this.getFeatures(this.startEvt);delete this.startEvt;for(var b,c,d={},e=0,f=a.length;e<f&&(b=a[e],c=b.layer,d[c.id]=!0,b=this.triggerEvent("featureclick",{feature:b}),!1!==b);++e);e=0;for(f=this.map.layers.length;e<f;++e)c=this.map.layers[e],c instanceof OpenLayers.Layer.Vector&&!d[c.id]&&this.triggerEvent("nofeatureclick",{layer:c})}},
2262 onMousemove:function(a){delete this.startEvt;var b=this.getFeatures(a),c={};a=[];for(var d,e=0,f=b.length;e<f;++e)d=b[e],c[d.id]=d,this.cache[d.id]||a.push(d);var b=[],g;for(g in this.cache)d=this.cache[g],d.layer&&d.layer.map?c[d.id]||b.push(d):delete this.cache[g];e=0;for(f=a.length;e<f&&(d=a[e],this.cache[d.id]=d,g=this.triggerEvent("featureover",{feature:d}),!1!==g);++e);e=0;for(f=b.length;e<f&&(d=b[e],delete this.cache[d.id],g=this.triggerEvent("featureout",{feature:d}),!1!==g);++e);},triggerEvent:function(a,
2263 b){var c=b.feature?b.feature.layer:b.layer,d=this.target.object;if(d instanceof OpenLayers.Map||d===c)return this.target.triggerEvent(a,b)},getFeatures:function(a){var b=a.clientX,c=a.clientY,d=[],e=[],f=[],g,h,k,l;for(l=this.map.layers.length-1;0<=l;--l)if(g=this.map.layers[l],"none"!==g.div.style.display)if(g.renderer instanceof OpenLayers.Renderer.Elements){if(g instanceof OpenLayers.Layer.Vector)for(h=document.elementFromPoint(b,c);h&&h._featureId;)(k=g.getFeatureById(h._featureId))?(d.push(k),
2264 h.style.display="none",e.push(h),h=document.elementFromPoint(b,c)):h=!1;f.push(g);g.div.style.display="none"}else g.renderer instanceof OpenLayers.Renderer.Canvas&&(k=g.renderer.getFeatureIdFromEvent(a))&&(d.push(k),f.push(g));l=0;for(a=e.length;l<a;++l)e[l].style.display="";for(l=f.length-1;0<=l;--l)f[l].div.style.display="block";return d},destroy:function(){for(var a=this.provides.length-1;0<=a;--a)delete this.target.extensions[this.provides[a]];this.map.events.un({mousemove:this.onMousemove,mousedown:this.start,
2265 mouseup:this.onClick,touchstart:this.start,touchmove:this.cancel,touchend:this.onClick,scope:this});delete this.cache;delete this.map;delete this.target}});OpenLayers.Events.nofeatureclick=OpenLayers.Events.featureclick;OpenLayers.Events.featureover=OpenLayers.Events.featureclick;OpenLayers.Events.featureout=OpenLayers.Events.featureclick;OpenLayers.Format.GPX=OpenLayers.Class(OpenLayers.Format.XML,{defaultDesc:"No description available",extractWaypoints:!0,extractTracks:!0,extractRoutes:!0,extractAttributes:!0,namespaces:{gpx:"http://www.topografix.com/GPX/1/1",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd",creator:"OpenLayers",initialize:function(a){this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,
2266 [a])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=[];if(this.extractTracks)for(var c=a.getElementsByTagName("trk"),d=0,e=c.length;d<e;d++){var f={};this.extractAttributes&&(f=this.parseAttributes(c[d]));for(var g=this.getElementsByTagNameNS(c[d],c[d].namespaceURI,"trkseg"),h=0,k=g.length;h<k;h++){var l=this.extractSegment(g[h],"trkpt");b.push(new OpenLayers.Feature.Vector(l,f))}}if(this.extractRoutes)for(e=a.getElementsByTagName("rte"),c=0,d=
2267 e.length;c<d;c++)f={},this.extractAttributes&&(f=this.parseAttributes(e[c])),g=this.extractSegment(e[c],"rtept"),b.push(new OpenLayers.Feature.Vector(g,f));if(this.extractWaypoints)for(a=a.getElementsByTagName("wpt"),c=0,e=a.length;c<e;c++)f={},this.extractAttributes&&(f=this.parseAttributes(a[c])),d=new OpenLayers.Geometry.Point(a[c].getAttribute("lon"),a[c].getAttribute("lat")),b.push(new OpenLayers.Feature.Vector(d,f));if(this.internalProjection&&this.externalProjection)for(f=0,a=b.length;f<a;f++)b[f].geometry.transform(this.externalProjection,
2268 this.internalProjection);return b},extractSegment:function(a,b){for(var c=this.getElementsByTagNameNS(a,a.namespaceURI,b),d=[],e=0,f=c.length;e<f;e++)d.push(new OpenLayers.Geometry.Point(c[e].getAttribute("lon"),c[e].getAttribute("lat")));return new OpenLayers.Geometry.LineString(d)},parseAttributes:function(a){var b={};a=a.firstChild;for(var c,d;a;)1==a.nodeType&&a.firstChild&&(c=a.firstChild,3==c.nodeType||4==c.nodeType)&&(d=a.prefix?a.nodeName.split(":")[1]:a.nodeName,"trkseg"!=d&&"rtept"!=d&&
2269 (b[d]=c.nodeValue)),a=a.nextSibling;return b},write:function(a,b){a=OpenLayers.Util.isArray(a)?a:[a];var c=this.createElementNS(this.namespaces.gpx,"gpx");c.setAttribute("version","1.1");c.setAttribute("creator",this.creator);this.setAttributes(c,{"xsi:schemaLocation":this.schemaLocation});b&&"object"==typeof b&&c.appendChild(this.buildMetadataNode(b));for(var d=0,e=a.length;d<e;d++)c.appendChild(this.buildFeatureNode(a[d]));return OpenLayers.Format.XML.prototype.write.apply(this,[c])},buildMetadataNode:function(a){for(var b=
2270 ["name","desc","author"],c=this.createElementNS(this.namespaces.gpx,"metadata"),d=0;d<b.length;d++){var e=b[d];if(a[e]){var f=this.createElementNS(this.namespaces.gpx,e);f.appendChild(this.createTextNode(a[e]));c.appendChild(f)}}return c},buildFeatureNode:function(a){var b=a.geometry,b=b.clone();this.internalProjection&&this.externalProjection&&b.transform(this.internalProjection,this.externalProjection);if("OpenLayers.Geometry.Point"==b.CLASS_NAME){var c=this.buildWptNode(b);this.appendAttributesNode(c,
2271 a);return c}c=this.createElementNS(this.namespaces.gpx,"trk");this.appendAttributesNode(c,a);a=this.buildTrkSegNode(b);a=OpenLayers.Util.isArray(a)?a:[a];for(var b=0,d=a.length;b<d;b++)c.appendChild(a[b]);return c},buildTrkSegNode:function(a){var b,c,d,e;if("OpenLayers.Geometry.LineString"==a.CLASS_NAME||"OpenLayers.Geometry.LinearRing"==a.CLASS_NAME){b=this.createElementNS(this.namespaces.gpx,"trkseg");c=0;for(d=a.components.length;c<d;c++)e=a.components[c],b.appendChild(this.buildTrkPtNode(e));
2272 return b}b=[];c=0;for(d=a.components.length;c<d;c++)b.push(this.buildTrkSegNode(a.components[c]));return b},buildTrkPtNode:function(a){var b=this.createElementNS(this.namespaces.gpx,"trkpt");b.setAttribute("lon",a.x);b.setAttribute("lat",a.y);return b},buildWptNode:function(a){var b=this.createElementNS(this.namespaces.gpx,"wpt");b.setAttribute("lon",a.x);b.setAttribute("lat",a.y);return b},appendAttributesNode:function(a,b){var c=this.createElementNS(this.namespaces.gpx,"name");c.appendChild(this.createTextNode(b.attributes.name||
2273 b.id));a.appendChild(c);c=this.createElementNS(this.namespaces.gpx,"desc");c.appendChild(this.createTextNode(b.attributes.description||this.defaultDesc));a.appendChild(c)},CLASS_NAME:"OpenLayers.Format.GPX"});OpenLayers.Format.WMSDescribeLayer=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.1",CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer"});OpenLayers.Format.WMSDescribeLayer.v1_1_1=OpenLayers.Class(OpenLayers.Format.WMSDescribeLayer,{initialize:function(a){OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this,[a])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));for(var b=a.documentElement.childNodes,c={layerDescriptions:[]},d,e,f=0;f<b.length;++f)if(d=b[f],e=d.nodeName,"LayerDescription"==e){e=d.getAttribute("name");var g="",h="",k="";d.getAttribute("owsType")?(g=d.getAttribute("owsType"),
2274 h=d.getAttribute("owsURL")):""!=d.getAttribute("wfs")?(g="WFS",h=d.getAttribute("wfs")):""!=d.getAttribute("wcs")&&(g="WCS",h=d.getAttribute("wcs"));d=d.getElementsByTagName("Query");0<d.length&&((k=d[0].getAttribute("typeName"))||(k=d[0].getAttribute("typename")));d={layerName:e,owsType:g,owsURL:h,typeName:k};c.layerDescriptions.push(d);c.length=c.layerDescriptions.length;c[c.length-1]=d}else if("ServiceException"==e)return{error:(new OpenLayers.Format.OGCExceptionReport).read(a)};return c},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer.v1_1_1"});
2275 OpenLayers.Format.WMSDescribeLayer.v1_1_0=OpenLayers.Format.WMSDescribeLayer.v1_1_1;OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,sphericalMercator:!1,zoomOffset:0,serverResolutions:null,initialize:function(a,b,c){if(c&&c.sphericalMercator||this.sphericalMercator)c=OpenLayers.Util.extend({projection:"EPSG:900913",numZoomLevels:19},c);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a||this.name,b||this.url,{},c])},clone:function(a){null==a&&(a=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,
2276 [a])},getURL:function(a){a=this.getXYZ(a);var b=this.url;OpenLayers.Util.isArray(b)&&(b=this.selectUrl(""+a.x+a.y+a.z,b));return OpenLayers.String.format(b,a)},getXYZ:function(a){var b=this.getServerResolution(),c=Math.round((a.left-this.maxExtent.left)/(b*this.tileSize.w));a=Math.round((this.maxExtent.top-a.top)/(b*this.tileSize.h));b=this.getServerZoom();if(this.wrapDateLine)var d=Math.pow(2,b),c=(c%d+d)%d;return{x:c,y:a,z:b}},setMap:function(a){OpenLayers.Layer.Grid.prototype.setMap.apply(this,
2277 arguments);this.tileOrigin||(this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom))},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",url:["http://a.tile.openstreetmap.org/${z}/${x}/${y}.png","http://b.tile.openstreetmap.org/${z}/${x}/${y}.png","http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"],attribution:"&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors",sphericalMercator:!0,wrapDateLine:!0,tileOptions:null,initialize:function(a,b,c){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);this.tileOptions=
2278 OpenLayers.Util.extend({crossOriginKeyword:"anonymous"},this.options&&this.options.tileOptions)},clone:function(a){null==a&&(a=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions()));return a=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[a])},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:!1,size:null,resolution:null,map:null,featureDx:0,initialize:function(a,b){this.container=OpenLayers.Util.getElement(a);OpenLayers.Util.extend(this,b)},destroy:function(){this.map=this.resolution=this.size=this.extent=this.container=null},supported:function(){return!1},setExtent:function(a,b){this.extent=a.clone();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var c=a.getWidth()/this.map.getExtent().getWidth();
2279 a=a.scale(1/c);this.extent=a.wrapDateLine(this.map.getMaxExtent()).scale(c)}b&&(this.resolution=null);return!0},setSize:function(a){this.size=a.clone();this.resolution=null},getResolution:function(){return this.resolution=this.resolution||this.map.getResolution()},drawFeature:function(a,b){null==b&&(b=a.style);if(a.geometry){var c=a.geometry.getBounds();if(c){var d;this.map.baseLayer&&this.map.baseLayer.wrapDateLine&&(d=this.map.getMaxExtent());c.intersectsBounds(this.extent,{worldBounds:d})?this.calculateFeatureDx(c,
2280 d):b={display:"none"};c=this.drawGeometry(a.geometry,b,a.id);if("none"!=b.display&&b.label&&!1!==c){d=a.geometry.getCentroid();if(b.labelXOffset||b.labelYOffset){var e=isNaN(b.labelXOffset)?0:b.labelXOffset,f=isNaN(b.labelYOffset)?0:b.labelYOffset,g=this.getResolution();d.move(e*g,f*g)}this.drawText(a.id,b,d)}else this.removeText(a.id);return c}}},calculateFeatureDx:function(a,b){this.featureDx=0;if(b){var c=b.getWidth();this.featureDx=Math.round(((a.left+a.right)/2-(this.extent.left+this.extent.right)/
2281 2)/c)*c}},drawGeometry:function(a,b,c){},drawText:function(a,b,c){},removeText:function(a){},clear:function(){},getFeatureIdFromEvent:function(a){},eraseFeatures:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=0,c=a.length;b<c;++b){var d=a[b];this.eraseGeometry(d.geometry,d.id);this.removeText(d.id)}},eraseGeometry:function(a,b){},moveRoot:function(a){},getRenderLayerId:function(){return this.container.id},applyDefaultSymbolizer:function(a){var b=OpenLayers.Util.extend({},OpenLayers.Renderer.defaultSymbolizer);
2282 !1===a.stroke&&(delete b.strokeWidth,delete b.strokeColor);!1===a.fill&&delete b.fillColor;OpenLayers.Util.extend(b,a);return b},CLASS_NAME:"OpenLayers.Renderer"});OpenLayers.Renderer.defaultSymbolizer={fillColor:"#000000",strokeColor:"#000000",strokeWidth:2,fillOpacity:1,strokeOpacity:1,pointRadius:0,labelAlign:"cm"};
2283 OpenLayers.Renderer.symbol={star:[350,75,379,161,469,161,397,215,423,301,350,250,277,301,303,215,231,161,321,161,350,75],cross:[4,0,6,0,6,4,10,4,10,6,6,6,6,10,4,10,4,6,0,6,0,4,4,4,4,0],x:[0,0,25,0,50,35,75,0,100,0,65,50,100,100,75,100,50,65,25,100,0,100,35,50,0,0],square:[0,0,0,1,1,1,1,0,0,0],triangle:[0,10,10,10,5,0,0,10]};OpenLayers.Renderer.Canvas=OpenLayers.Class(OpenLayers.Renderer,{hitDetection:!0,hitOverflow:0,canvas:null,features:null,pendingRedraw:!1,cachedSymbolBounds:{},initialize:function(a,b){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.root=document.createElement("canvas");this.container.appendChild(this.root);this.canvas=this.root.getContext("2d");this.features={};this.hitDetection&&(this.hitCanvas=document.createElement("canvas"),this.hitContext=this.hitCanvas.getContext("2d"))},
2284 setExtent:function(){OpenLayers.Renderer.prototype.setExtent.apply(this,arguments);return!1},eraseGeometry:function(a,b){this.eraseFeatures(this.features[b][0])},supported:function(){return OpenLayers.CANVAS_SUPPORTED},setSize:function(a){this.size=a.clone();var b=this.root;b.style.width=a.w+"px";b.style.height=a.h+"px";b.width=a.w;b.height=a.h;this.resolution=null;this.hitDetection&&(b=this.hitCanvas,b.style.width=a.w+"px",b.style.height=a.h+"px",b.width=a.w,b.height=a.h)},drawFeature:function(a,
2285 b){var c;if(a.geometry){b=this.applyDefaultSymbolizer(b||a.style);c=a.geometry.getBounds();var d;this.map.baseLayer&&this.map.baseLayer.wrapDateLine&&(d=this.map.getMaxExtent());d=c&&c.intersectsBounds(this.extent,{worldBounds:d});(c="none"!==b.display&&!!c&&d)?this.features[a.id]=[a,b]:delete this.features[a.id];this.pendingRedraw=!0}this.pendingRedraw&&!this.locked&&(this.redraw(),this.pendingRedraw=!1);return c},drawGeometry:function(a,b,c){var d=a.CLASS_NAME;if("OpenLayers.Geometry.Collection"==
2286 d||"OpenLayers.Geometry.MultiPoint"==d||"OpenLayers.Geometry.MultiLineString"==d||"OpenLayers.Geometry.MultiPolygon"==d)for(d=0;d<a.components.length;d++)this.drawGeometry(a.components[d],b,c);else switch(a.CLASS_NAME){case "OpenLayers.Geometry.Point":this.drawPoint(a,b,c);break;case "OpenLayers.Geometry.LineString":this.drawLineString(a,b,c);break;case "OpenLayers.Geometry.LinearRing":this.drawLinearRing(a,b,c);break;case "OpenLayers.Geometry.Polygon":this.drawPolygon(a,b,c)}},drawExternalGraphic:function(a,
2287 b,c){var d=new Image,e=b.title||b.graphicTitle;e&&(d.title=e);var f=b.graphicWidth||b.graphicHeight,g=b.graphicHeight||b.graphicWidth,f=f?f:2*b.pointRadius,g=g?g:2*b.pointRadius,h=void 0!=b.graphicXOffset?b.graphicXOffset:-(0.5*f),k=void 0!=b.graphicYOffset?b.graphicYOffset:-(0.5*g),l=b.graphicOpacity||b.fillOpacity;d.onload=OpenLayers.Function.bind(function(){if(this.features[c]){var b=this.getLocalXY(a),e=b[0],b=b[1];if(!isNaN(e)&&!isNaN(b)){var e=e+h|0,b=b+k|0,p=this.canvas;p.globalAlpha=l;var q=
2288 OpenLayers.Renderer.Canvas.drawImageScaleFactor||(OpenLayers.Renderer.Canvas.drawImageScaleFactor=/android 2.1/.test(navigator.userAgent.toLowerCase())?320/window.screen.width:1);p.drawImage(d,e*q,b*q,f*q,g*q);this.hitDetection&&(this.setHitContextStyle("fill",c),this.hitContext.fillRect(e,b,f,g))}}},this);d.src=b.externalGraphic},drawNamedSymbol:function(a,b,c){var d,e,f,g;f=Math.PI/180;var h=OpenLayers.Renderer.symbol[b.graphicName];if(!h)throw Error(b.graphicName+" is not a valid symbol name");
2289 if(!(!h.length||2>h.length||(a=this.getLocalXY(a),e=a[0],g=a[1],isNaN(e)||isNaN(g)))){this.canvas.lineCap="round";this.canvas.lineJoin="round";this.hitDetection&&(this.hitContext.lineCap="round",this.hitContext.lineJoin="round");if(b.graphicName in this.cachedSymbolBounds)d=this.cachedSymbolBounds[b.graphicName];else{d=new OpenLayers.Bounds;for(a=0;a<h.length;a+=2)d.extend(new OpenLayers.LonLat(h[a],h[a+1]));this.cachedSymbolBounds[b.graphicName]=d}this.canvas.save();this.hitDetection&&this.hitContext.save();
2290 this.canvas.translate(e,g);this.hitDetection&&this.hitContext.translate(e,g);a=f*b.rotation;isNaN(a)||(this.canvas.rotate(a),this.hitDetection&&this.hitContext.rotate(a));f=2*b.pointRadius/Math.max(d.getWidth(),d.getHeight());this.canvas.scale(f,f);this.hitDetection&&this.hitContext.scale(f,f);a=d.getCenterLonLat().lon;d=d.getCenterLonLat().lat;this.canvas.translate(-a,-d);this.hitDetection&&this.hitContext.translate(-a,-d);g=b.strokeWidth;b.strokeWidth=g/f;if(!1!==b.fill){this.setCanvasStyle("fill",
2291 b);this.canvas.beginPath();for(a=0;a<h.length;a+=2)d=h[a],e=h[a+1],0==a&&this.canvas.moveTo(d,e),this.canvas.lineTo(d,e);this.canvas.closePath();this.canvas.fill();if(this.hitDetection){this.setHitContextStyle("fill",c,b);this.hitContext.beginPath();for(a=0;a<h.length;a+=2)d=h[a],e=h[a+1],0==a&&this.canvas.moveTo(d,e),this.hitContext.lineTo(d,e);this.hitContext.closePath();this.hitContext.fill()}}if(!1!==b.stroke){this.setCanvasStyle("stroke",b);this.canvas.beginPath();for(a=0;a<h.length;a+=2)d=h[a],
2292 e=h[a+1],0==a&&this.canvas.moveTo(d,e),this.canvas.lineTo(d,e);this.canvas.closePath();this.canvas.stroke();if(this.hitDetection){this.setHitContextStyle("stroke",c,b,f);this.hitContext.beginPath();for(a=0;a<h.length;a+=2)d=h[a],e=h[a+1],0==a&&this.hitContext.moveTo(d,e),this.hitContext.lineTo(d,e);this.hitContext.closePath();this.hitContext.stroke()}}b.strokeWidth=g;this.canvas.restore();this.hitDetection&&this.hitContext.restore();this.setCanvasStyle("reset")}},setCanvasStyle:function(a,b){"fill"===
2293 a?(this.canvas.globalAlpha=b.fillOpacity,this.canvas.fillStyle=b.fillColor):"stroke"===a?(this.canvas.globalAlpha=b.strokeOpacity,this.canvas.strokeStyle=b.strokeColor,this.canvas.lineWidth=b.strokeWidth):(this.canvas.globalAlpha=0,this.canvas.lineWidth=1)},featureIdToHex:function(a){a=Number(a.split("_").pop())+1;16777216<=a&&(this.hitOverflow=a-16777215,a=a%16777216+1);a="000000"+a.toString(16);var b=a.length;return a="#"+a.substring(b-6,b)},setHitContextStyle:function(a,b,c,d){b=this.featureIdToHex(b);
2294 "fill"==a?(this.hitContext.globalAlpha=1,this.hitContext.fillStyle=b):"stroke"==a?(this.hitContext.globalAlpha=1,this.hitContext.strokeStyle=b,"undefined"===typeof d?this.hitContext.lineWidth=c.strokeWidth+2:isNaN(d)||(this.hitContext.lineWidth=c.strokeWidth+2/d)):(this.hitContext.globalAlpha=0,this.hitContext.lineWidth=1)},drawPoint:function(a,b,c){if(!1!==b.graphic)if(b.externalGraphic)this.drawExternalGraphic(a,b,c);else if(b.graphicName&&"circle"!=b.graphicName)this.drawNamedSymbol(a,b,c);else{var d=
2295 this.getLocalXY(a);a=d[0];d=d[1];if(!isNaN(a)&&!isNaN(d)){var e=2*Math.PI,f=b.pointRadius;!1!==b.fill&&(this.setCanvasStyle("fill",b),this.canvas.beginPath(),this.canvas.arc(a,d,f,0,e,!0),this.canvas.fill(),this.hitDetection&&(this.setHitContextStyle("fill",c,b),this.hitContext.beginPath(),this.hitContext.arc(a,d,f,0,e,!0),this.hitContext.fill()));!1!==b.stroke&&(this.setCanvasStyle("stroke",b),this.canvas.beginPath(),this.canvas.arc(a,d,f,0,e,!0),this.canvas.stroke(),this.hitDetection&&(this.setHitContextStyle("stroke",
2296 c,b),this.hitContext.beginPath(),this.hitContext.arc(a,d,f,0,e,!0),this.hitContext.stroke()),this.setCanvasStyle("reset"))}}},drawLineString:function(a,b,c){b=OpenLayers.Util.applyDefaults({fill:!1},b);this.drawLinearRing(a,b,c)},drawLinearRing:function(a,b,c){!1!==b.fill&&(this.setCanvasStyle("fill",b),this.renderPath(this.canvas,a,b,c,"fill"),this.hitDetection&&(this.setHitContextStyle("fill",c,b),this.renderPath(this.hitContext,a,b,c,"fill")));!1!==b.stroke&&(this.setCanvasStyle("stroke",b),this.renderPath(this.canvas,
2297 a,b,c,"stroke"),this.hitDetection&&(this.setHitContextStyle("stroke",c,b),this.renderPath(this.hitContext,a,b,c,"stroke")));this.setCanvasStyle("reset")},renderPath:function(a,b,c,d,e){b=b.components;c=b.length;a.beginPath();d=this.getLocalXY(b[0]);var f=d[1];if(!isNaN(d[0])&&!isNaN(f)){a.moveTo(d[0],d[1]);for(d=1;d<c;++d)f=this.getLocalXY(b[d]),a.lineTo(f[0],f[1]);"fill"===e?a.fill():a.stroke()}},drawPolygon:function(a,b,c){a=a.components;var d=a.length;this.drawLinearRing(a[0],b,c);for(var e=1;e<
2298 d;++e)this.canvas.globalCompositeOperation="destination-out",this.hitDetection&&(this.hitContext.globalCompositeOperation="destination-out"),this.drawLinearRing(a[e],OpenLayers.Util.applyDefaults({stroke:!1,fillOpacity:1},b),c),this.canvas.globalCompositeOperation="source-over",this.hitDetection&&(this.hitContext.globalCompositeOperation="source-over"),this.drawLinearRing(a[e],OpenLayers.Util.applyDefaults({fill:!1},b),c)},drawText:function(a,b){var c=this.getLocalXY(a);this.setCanvasStyle("reset");
2299 this.canvas.fillStyle=b.fontColor;this.canvas.globalAlpha=b.fontOpacity||1;var d=[b.fontStyle?b.fontStyle:"normal","normal",b.fontWeight?b.fontWeight:"normal",b.fontSize?b.fontSize:"1em",b.fontFamily?b.fontFamily:"sans-serif"].join(" "),e=b.label.split("\n"),f=e.length;if(this.canvas.fillText){this.canvas.font=d;this.canvas.textAlign=OpenLayers.Renderer.Canvas.LABEL_ALIGN[b.labelAlign[0]]||"center";this.canvas.textBaseline=OpenLayers.Renderer.Canvas.LABEL_ALIGN[b.labelAlign[1]]||"middle";var g=OpenLayers.Renderer.Canvas.LABEL_FACTOR[b.labelAlign[1]];
2300 null==g&&(g=-0.5);d=this.canvas.measureText("Mg").height||this.canvas.measureText("xx").width;c[1]+=d*g*(f-1);for(g=0;g<f;g++)b.labelOutlineWidth&&(this.canvas.save(),this.canvas.globalAlpha=b.labelOutlineOpacity||b.fontOpacity||1,this.canvas.strokeStyle=b.labelOutlineColor,this.canvas.lineWidth=b.labelOutlineWidth,this.canvas.strokeText(e[g],c[0],c[1]+d*g+1),this.canvas.restore()),this.canvas.fillText(e[g],c[0],c[1]+d*g)}else if(this.canvas.mozDrawText){this.canvas.mozTextStyle=d;var h=OpenLayers.Renderer.Canvas.LABEL_FACTOR[b.labelAlign[0]];
2301 null==h&&(h=-0.5);g=OpenLayers.Renderer.Canvas.LABEL_FACTOR[b.labelAlign[1]];null==g&&(g=-0.5);d=this.canvas.mozMeasureText("xx");c[1]+=d*(1+g*f);for(g=0;g<f;g++){var k=c[0]+h*this.canvas.mozMeasureText(e[g]),l=c[1]+g*d;this.canvas.translate(k,l);this.canvas.mozDrawText(e[g]);this.canvas.translate(-k,-l)}}this.setCanvasStyle("reset")},getLocalXY:function(a){var b=this.getResolution(),c=this.extent;return[(a.x-this.featureDx)/b+-c.left/b,c.top/b-a.y/b]},clear:function(){var a=this.root.height,b=this.root.width;
2302 this.canvas.clearRect(0,0,b,a);this.features={};this.hitDetection&&this.hitContext.clearRect(0,0,b,a)},getFeatureIdFromEvent:function(a){var b;if(this.hitDetection&&"none"!==this.root.style.display&&!this.map.dragging&&(a=a.xy,a=this.hitContext.getImageData(a.x|0,a.y|0,1,1).data,255===a[3]&&(a=a[2]+256*(a[1]+256*a[0])))){a="OpenLayers_Feature_Vector_"+(a-1+this.hitOverflow);try{b=this.features[a][0]}catch(c){}}return b},eraseFeatures:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=0;b<a.length;++b)delete this.features[a[b].id];
2303 this.redraw()},redraw:function(){if(!this.locked){var a=this.root.height,b=this.root.width;this.canvas.clearRect(0,0,b,a);this.hitDetection&&this.hitContext.clearRect(0,0,b,a);var a=[],c,d,e=this.map.baseLayer&&this.map.baseLayer.wrapDateLine&&this.map.getMaxExtent(),f;for(f in this.features)this.features.hasOwnProperty(f)&&(b=this.features[f][0],c=b.geometry,this.calculateFeatureDx(c.getBounds(),e),d=this.features[f][1],this.drawGeometry(c,d,b.id),d.label&&a.push([b,d]));b=0;for(c=a.length;b<c;++b)f=
2304 a[b],this.drawText(f[0].geometry.getCentroid(),f[1])}},CLASS_NAME:"OpenLayers.Renderer.Canvas"});OpenLayers.Renderer.Canvas.LABEL_ALIGN={l:"left",r:"right",t:"top",b:"bottom"};OpenLayers.Renderer.Canvas.LABEL_FACTOR={l:0,r:-1,t:0,b:-1};OpenLayers.Renderer.Canvas.drawImageScaleFactor=null;OpenLayers.Format.OSM=OpenLayers.Class(OpenLayers.Format.XML,{checkTags:!1,interestingTagsExclude:null,areaTags:null,initialize:function(a){var b={interestingTagsExclude:"source source_ref source:ref history attribution created_by".split(" "),areaTags:"area building leisure tourism ruins historic landuse military natural sport".split(" ")},b=OpenLayers.Util.extend(b,a),c={};for(a=0;a<b.interestingTagsExclude.length;a++)c[b.interestingTagsExclude[a]]=!0;b.interestingTagsExclude=c;c={};for(a=0;a<b.areaTags.length;a++)c[b.areaTags[a]]=
2305 !0;b.areaTags=c;this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[b])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=this.getNodes(a),c=this.getWays(a);a=Array(c.length);for(var d=0;d<c.length;d++){for(var e=Array(c[d].nodes.length),f=this.isWayArea(c[d])?1:0,g=0;g<c[d].nodes.length;g++){var h=b[c[d].nodes[g]],k=new OpenLayers.Geometry.Point(h.lon,h.lat);k.osm_id=parseInt(c[d].nodes[g]);
2306 e[g]=k;h.used=!0}h=null;h=f?new OpenLayers.Geometry.Polygon(new OpenLayers.Geometry.LinearRing(e)):new OpenLayers.Geometry.LineString(e);this.internalProjection&&this.externalProjection&&h.transform(this.externalProjection,this.internalProjection);e=new OpenLayers.Feature.Vector(h,c[d].tags);e.osm_id=parseInt(c[d].id);e.fid="way."+e.osm_id;a[d]=e}for(var l in b){h=b[l];if(!h.used||this.checkTags){c=null;if(this.checkTags){c=this.getTags(h.node,!0);if(h.used&&!c[1])continue;c=c[0]}else c=this.getTags(h.node);
2307 e=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(h.lon,h.lat),c);this.internalProjection&&this.externalProjection&&e.geometry.transform(this.externalProjection,this.internalProjection);e.osm_id=parseInt(l);e.fid="node."+e.osm_id;a.push(e)}h.node=null}return a},getNodes:function(a){a=a.getElementsByTagName("node");for(var b={},c=0;c<a.length;c++){var d=a[c],e=d.getAttribute("id");b[e]={lat:d.getAttribute("lat"),lon:d.getAttribute("lon"),node:d}}return b},getWays:function(a){a=a.getElementsByTagName("way");
2308 for(var b=[],c=0;c<a.length;c++){var d=a[c],e={id:d.getAttribute("id")};e.tags=this.getTags(d);d=d.getElementsByTagName("nd");e.nodes=Array(d.length);for(var f=0;f<d.length;f++)e.nodes[f]=d[f].getAttribute("ref");b.push(e)}return b},getTags:function(a,b){for(var c=a.getElementsByTagName("tag"),d={},e=!1,f=0;f<c.length;f++){var g=c[f].getAttribute("k");d[g]=c[f].getAttribute("v");b&&(this.interestingTagsExclude[g]||(e=!0))}return b?[d,e]:d},isWayArea:function(a){var b=!1,c=!1;a.nodes[0]==a.nodes[a.nodes.length-
2309 1]&&(b=!0);if(this.checkTags)for(var d in a.tags)if(this.areaTags[d]){c=!0;break}return b&&(this.checkTags?c:!0)},write:function(a){OpenLayers.Util.isArray(a)||(a=[a]);this.osm_id=1;this.created_nodes={};var b=this.createElementNS(null,"osm");b.setAttribute("version","0.5");b.setAttribute("generator","OpenLayers "+OpenLayers.VERSION_NUMBER);for(var c=a.length-1;0<=c;c--)for(var d=this.createFeatureNodes(a[c]),e=0;e<d.length;e++)b.appendChild(d[e]);return OpenLayers.Format.XML.prototype.write.apply(this,
2310 [b])},createFeatureNodes:function(a){var b=[],c=a.geometry.CLASS_NAME,c=c.substring(c.lastIndexOf(".")+1),c=c.toLowerCase();(c=this.createXML[c])&&(b=c.apply(this,[a]));return b},createXML:{point:function(a){var b=null,c=a.geometry?a.geometry:a;this.internalProjection&&this.externalProjection&&(c=c.clone(),c.transform(this.internalProjection,this.externalProjection));var d=!1;a.osm_id?(b=a.osm_id,this.created_nodes[b]&&(d=!0)):(b=-this.osm_id,this.osm_id++);var e=d?this.created_nodes[b]:this.createElementNS(null,
2311 "node");this.created_nodes[b]=e;e.setAttribute("id",b);e.setAttribute("lon",c.x);e.setAttribute("lat",c.y);a.attributes&&this.serializeTags(a,e);this.setState(a,e);return d?[]:[e]},linestring:function(a){var b,c=[],d=a.geometry;a.osm_id?b=a.osm_id:(b=-this.osm_id,this.osm_id++);var e=this.createElementNS(null,"way");e.setAttribute("id",b);for(b=0;b<d.components.length;b++){var f=this.createXML.point.apply(this,[d.components[b]]);if(f.length){var f=f[0],g=f.getAttribute("id");c.push(f)}else g=d.components[b].osm_id,
2312 f=this.created_nodes[g];this.setState(a,f);f=this.createElementNS(null,"nd");f.setAttribute("ref",g);e.appendChild(f)}this.serializeTags(a,e);c.push(e);return c},polygon:function(a){var b=OpenLayers.Util.extend({area:"yes"},a.attributes),b=new OpenLayers.Feature.Vector(a.geometry.components[0],b);b.osm_id=a.osm_id;return this.createXML.linestring.apply(this,[b])}},serializeTags:function(a,b){for(var c in a.attributes){var d=this.createElementNS(null,"tag");d.setAttribute("k",c);d.setAttribute("v",
2313 a.attributes[c]);b.appendChild(d)}},setState:function(a,b){if(a.state){var c=null;switch(a.state){case OpenLayers.State.UPDATE:case OpenLayers.State.DELETE:c="delete"}c&&b.setAttribute("action",c)}},CLASS_NAME:"OpenLayers.Format.OSM"});OpenLayers.Handler.Keyboard=OpenLayers.Class(OpenLayers.Handler,{KEY_EVENTS:["keydown","keyup"],eventListener:null,observeElement:null,initialize:function(a,b,c){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.eventListener=OpenLayers.Function.bindAsEventListener(this.handleKeyEvent,this)},destroy:function(){this.deactivate();this.eventListener=null;OpenLayers.Handler.prototype.destroy.apply(this,arguments)},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,
2314 arguments)){this.observeElement=this.observeElement||document;for(var a=0,b=this.KEY_EVENTS.length;a<b;a++)OpenLayers.Event.observe(this.observeElement,this.KEY_EVENTS[a],this.eventListener);return!0}return!1},deactivate:function(){var a=!1;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){for(var a=0,b=this.KEY_EVENTS.length;a<b;a++)OpenLayers.Event.stopObserving(this.observeElement,this.KEY_EVENTS[a],this.eventListener);a=!0}return a},handleKeyEvent:function(a){this.checkModifiers(a)&&
2315 this.callback(a.type,[a])},CLASS_NAME:"OpenLayers.Handler.Keyboard"});OpenLayers.Control.ModifyFeature=OpenLayers.Class(OpenLayers.Control,{documentDrag:!1,geometryTypes:null,clickout:!0,toggle:!0,standalone:!1,layer:null,feature:null,vertex:null,vertices:null,virtualVertices:null,handlers:null,deleteCodes:null,virtualStyle:null,vertexRenderIntent:null,mode:null,createVertices:!0,modified:!1,radiusHandle:null,dragHandle:null,onModificationStart:function(){},onModification:function(){},onModificationEnd:function(){},initialize:function(a,b){b=b||{};this.layer=a;this.vertices=
2316 [];this.virtualVertices=[];this.virtualStyle=OpenLayers.Util.extend({},this.layer.style||this.layer.styleMap.createSymbolizer(null,b.vertexRenderIntent));this.virtualStyle.fillOpacity=0.3;this.virtualStyle.strokeOpacity=0.3;this.deleteCodes=[46,68];this.mode=OpenLayers.Control.ModifyFeature.RESHAPE;OpenLayers.Control.prototype.initialize.apply(this,[b]);OpenLayers.Util.isArray(this.deleteCodes)||(this.deleteCodes=[this.deleteCodes]);var c={documentDrag:this.documentDrag,stopDown:!1};this.handlers=
2317 {keyboard:new OpenLayers.Handler.Keyboard(this,{keydown:this.handleKeypress}),drag:new OpenLayers.Handler.Drag(this,{down:function(a){this.vertex=null;(a=this.layer.getFeatureFromEvent(this.handlers.drag.evt))?this.dragStart(a):this.clickout&&(this._unselect=this.feature)},move:function(a){delete this._unselect;this.vertex&&this.dragVertex(this.vertex,a)},up:function(){this.handlers.drag.stopDown=!1;this._unselect&&(this.unselectFeature(this._unselect),delete this._unselect)},done:function(a){this.vertex&&
2318 this.dragComplete(this.vertex)}},c)}},destroy:function(){this.map&&this.map.events.un({removelayer:this.handleMapEvents,changelayer:this.handleMapEvents,scope:this});this.layer=null;OpenLayers.Control.prototype.destroy.apply(this,[])},activate:function(){this.moveLayerToTop();this.map.events.on({removelayer:this.handleMapEvents,changelayer:this.handleMapEvents,scope:this});return this.handlers.keyboard.activate()&&this.handlers.drag.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments)},
2319 deactivate:function(){var a=!1;OpenLayers.Control.prototype.deactivate.apply(this,arguments)&&(this.moveLayerBack(),this.map.events.un({removelayer:this.handleMapEvents,changelayer:this.handleMapEvents,scope:this}),this.layer.removeFeatures(this.vertices,{silent:!0}),this.layer.removeFeatures(this.virtualVertices,{silent:!0}),this.vertices=[],this.handlers.drag.deactivate(),this.handlers.keyboard.deactivate(),(a=this.feature)&&(a.geometry&&a.layer)&&this.unselectFeature(a),a=!0);return a},beforeSelectFeature:function(a){return this.layer.events.triggerEvent("beforefeaturemodified",
2320 {feature:a})},selectFeature:function(a){if(!(this.feature===a||this.geometryTypes&&-1==OpenLayers.Util.indexOf(this.geometryTypes,a.geometry.CLASS_NAME))){!1!==this.beforeSelectFeature(a)&&(this.feature&&this.unselectFeature(this.feature),this.feature=a,this.layer.selectedFeatures.push(a),this.layer.drawFeature(a,"select"),this.modified=!1,this.resetVertices(),this.onModificationStart(this.feature));var b=a.modified;!a.geometry||b&&b.geometry||(this._originalGeometry=a.geometry.clone())}},unselectFeature:function(a){this.layer.removeFeatures(this.vertices,
2321 {silent:!0});this.vertices=[];this.layer.destroyFeatures(this.virtualVertices,{silent:!0});this.virtualVertices=[];this.dragHandle&&(this.layer.destroyFeatures([this.dragHandle],{silent:!0}),delete this.dragHandle);this.radiusHandle&&(this.layer.destroyFeatures([this.radiusHandle],{silent:!0}),delete this.radiusHandle);this.layer.drawFeature(this.feature,"default");this.feature=null;OpenLayers.Util.removeItem(this.layer.selectedFeatures,a);this.onModificationEnd(a);this.layer.events.triggerEvent("afterfeaturemodified",
2322 {feature:a,modified:this.modified});this.modified=!1},dragStart:function(a){var b="OpenLayers.Geometry.Point"==a.geometry.CLASS_NAME;this.standalone||(a._sketch||!b)&&a._sketch||(this.toggle&&this.feature===a&&(this._unselect=a),this.selectFeature(a));if(a._sketch||b)this.vertex=a,this.handlers.drag.stopDown=!0},dragVertex:function(a,b){var c=this.map.getLonLatFromViewPortPx(b),d=a.geometry;d.move(c.lon-d.x,c.lat-d.y);this.modified=!0;"OpenLayers.Geometry.Point"==this.feature.geometry.CLASS_NAME?
2323 this.layer.events.triggerEvent("vertexmodified",{vertex:a.geometry,feature:this.feature,pixel:b}):(a._index?(a.geometry.parent.addComponent(a.geometry,a._index),delete a._index,OpenLayers.Util.removeItem(this.virtualVertices,a),this.vertices.push(a)):a==this.dragHandle?(this.layer.removeFeatures(this.vertices,{silent:!0}),this.vertices=[],this.radiusHandle&&(this.layer.destroyFeatures([this.radiusHandle],{silent:!0}),this.radiusHandle=null)):a!==this.radiusHandle&&this.layer.events.triggerEvent("vertexmodified",
2324 {vertex:a.geometry,feature:this.feature,pixel:b}),0<this.virtualVertices.length&&(this.layer.destroyFeatures(this.virtualVertices,{silent:!0}),this.virtualVertices=[]),this.layer.drawFeature(this.feature,this.standalone?void 0:"select"));this.layer.drawFeature(a)},dragComplete:function(a){this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature})},setFeatureState:function(){if(this.feature.state!=OpenLayers.State.INSERT&&
2325 this.feature.state!=OpenLayers.State.DELETE&&(this.feature.state=OpenLayers.State.UPDATE,this.modified&&this._originalGeometry)){var a=this.feature;a.modified=OpenLayers.Util.extend(a.modified,{geometry:this._originalGeometry});delete this._originalGeometry}},resetVertices:function(){0<this.vertices.length&&(this.layer.removeFeatures(this.vertices,{silent:!0}),this.vertices=[]);0<this.virtualVertices.length&&(this.layer.removeFeatures(this.virtualVertices,{silent:!0}),this.virtualVertices=[]);this.dragHandle&&
2326 (this.layer.destroyFeatures([this.dragHandle],{silent:!0}),this.dragHandle=null);this.radiusHandle&&(this.layer.destroyFeatures([this.radiusHandle],{silent:!0}),this.radiusHandle=null);this.feature&&"OpenLayers.Geometry.Point"!=this.feature.geometry.CLASS_NAME&&(this.mode&OpenLayers.Control.ModifyFeature.DRAG&&this.collectDragHandle(),this.mode&(OpenLayers.Control.ModifyFeature.ROTATE|OpenLayers.Control.ModifyFeature.RESIZE)&&this.collectRadiusHandle(),this.mode&OpenLayers.Control.ModifyFeature.RESHAPE&&
2327 (this.mode&OpenLayers.Control.ModifyFeature.RESIZE||this.collectVertices()))},handleKeypress:function(a){var b=a.keyCode;this.feature&&-1!=OpenLayers.Util.indexOf(this.deleteCodes,b)&&(b=this.layer.getFeatureFromEvent(this.handlers.drag.evt))&&(-1!=OpenLayers.Util.indexOf(this.vertices,b)&&!this.handlers.drag.dragging&&b.geometry.parent)&&(b.geometry.parent.removeComponent(b.geometry),this.layer.events.triggerEvent("vertexremoved",{vertex:b.geometry,feature:this.feature,pixel:a.xy}),this.layer.drawFeature(this.feature,
2328 this.standalone?void 0:"select"),this.modified=!0,this.resetVertices(),this.setFeatureState(),this.onModification(this.feature),this.layer.events.triggerEvent("featuremodified",{feature:this.feature}))},collectVertices:function(){function a(c){var d,e,f;if("OpenLayers.Geometry.Point"==c.CLASS_NAME)e=new OpenLayers.Feature.Vector(c),e._sketch=!0,e.renderIntent=b.vertexRenderIntent,b.vertices.push(e);else{f=c.components.length;"OpenLayers.Geometry.LinearRing"==c.CLASS_NAME&&(f-=1);for(d=0;d<f;++d)e=
2329 c.components[d],"OpenLayers.Geometry.Point"==e.CLASS_NAME?(e=new OpenLayers.Feature.Vector(e),e._sketch=!0,e.renderIntent=b.vertexRenderIntent,b.vertices.push(e)):a(e);if(b.createVertices&&"OpenLayers.Geometry.MultiPoint"!=c.CLASS_NAME)for(d=0,f=c.components.length;d<f-1;++d){e=c.components[d];var g=c.components[d+1];"OpenLayers.Geometry.Point"==e.CLASS_NAME&&"OpenLayers.Geometry.Point"==g.CLASS_NAME&&(e=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point((e.x+g.x)/2,(e.y+g.y)/2),null,b.virtualStyle),
2330 e.geometry.parent=c,e._index=d+1,e._sketch=!0,b.virtualVertices.push(e))}}}this.vertices=[];this.virtualVertices=[];var b=this;a.call(this,this.feature.geometry);this.layer.addFeatures(this.virtualVertices,{silent:!0});this.layer.addFeatures(this.vertices,{silent:!0})},collectDragHandle:function(){var a=this.feature.geometry,b=a.getBounds().getCenterLonLat(),b=new OpenLayers.Geometry.Point(b.lon,b.lat),c=new OpenLayers.Feature.Vector(b);b.move=function(b,c){OpenLayers.Geometry.Point.prototype.move.call(this,
2331 b,c);a.move(b,c)};c._sketch=!0;this.dragHandle=c;this.dragHandle.renderIntent=this.vertexRenderIntent;this.layer.addFeatures([this.dragHandle],{silent:!0})},collectRadiusHandle:function(){var a=this.feature.geometry,b=a.getBounds(),c=b.getCenterLonLat(),d=new OpenLayers.Geometry.Point(c.lon,c.lat),b=new OpenLayers.Geometry.Point(b.right,b.bottom),c=new OpenLayers.Feature.Vector(b),e=this.mode&OpenLayers.Control.ModifyFeature.RESIZE,f=this.mode&OpenLayers.Control.ModifyFeature.RESHAPE,g=this.mode&
2332 OpenLayers.Control.ModifyFeature.ROTATE;b.move=function(b,c){OpenLayers.Geometry.Point.prototype.move.call(this,b,c);var l=this.x-d.x,m=this.y-d.y,n=l-b,p=m-c;if(g){var q=Math.atan2(p,n),q=Math.atan2(m,l)-q,q=q*(180/Math.PI);a.rotate(q,d)}if(e){var r;f?(m/=p,r=l/n/m):(n=Math.sqrt(n*n+p*p),m=Math.sqrt(l*l+m*m)/n);a.resize(m,d,r)}};c._sketch=!0;this.radiusHandle=c;this.radiusHandle.renderIntent=this.vertexRenderIntent;this.layer.addFeatures([this.radiusHandle],{silent:!0})},setMap:function(a){this.handlers.drag.setMap(a);
2333 OpenLayers.Control.prototype.setMap.apply(this,arguments)},handleMapEvents:function(a){"removelayer"!=a.type&&"order"!=a.property||this.moveLayerToTop()},moveLayerToTop:function(){var a=Math.max(this.map.Z_INDEX_BASE.Feature-1,this.layer.getZIndex())+1;this.layer.setZIndex(a)},moveLayerBack:function(){var a=this.layer.getZIndex()-1;a>=this.map.Z_INDEX_BASE.Feature?this.layer.setZIndex(a):this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer))},CLASS_NAME:"OpenLayers.Control.ModifyFeature"});
2334 OpenLayers.Control.ModifyFeature.RESHAPE=1;OpenLayers.Control.ModifyFeature.RESIZE=2;OpenLayers.Control.ModifyFeature.ROTATE=4;OpenLayers.Control.ModifyFeature.DRAG=8;OpenLayers.Layer.Bing=OpenLayers.Class(OpenLayers.Layer.XYZ,{key:null,serverResolutions:[156543.03390625,78271.516953125,39135.7584765625,19567.87923828125,9783.939619140625,4891.9698095703125,2445.9849047851562,1222.9924523925781,611.4962261962891,305.74811309814453,152.87405654907226,76.43702827453613,38.218514137268066,19.109257068634033,9.554628534317017,4.777314267158508,2.388657133579254,1.194328566789627,0.5971642833948135,0.29858214169740677,0.14929107084870338,0.07464553542435169],attributionTemplate:'<span class="olBingAttribution ${type}"><div><a target="_blank" href="http://www.bing.com/maps/"><img src="${logo}" /></a></div>${copyrights}<a style="white-space: nowrap" target="_blank" href="http://www.microsoft.com/maps/product/terms.html">Terms of Use</a></span>',
2335 metadata:null,protocolRegex:/^http:/i,type:"Road",culture:"en-US",metadataParams:null,tileOptions:null,protocol:~window.location.href.indexOf("http")?"":"http:",initialize:function(a){a=OpenLayers.Util.applyDefaults({sphericalMercator:!0},a);OpenLayers.Layer.XYZ.prototype.initialize.apply(this,[a.name||"Bing "+(a.type||this.type),null,a]);this.tileOptions=OpenLayers.Util.extend({crossOriginKeyword:"anonymous"},this.options.tileOptions);this.loadMetadata()},loadMetadata:function(){this._callbackId=
2336 "_callback_"+this.id.replace(/\./g,"_");window[this._callbackId]=OpenLayers.Function.bind(OpenLayers.Layer.Bing.processMetadata,this);var a=OpenLayers.Util.applyDefaults({key:this.key,jsonp:this._callbackId,include:"ImageryProviders"},this.metadataParams),a=this.protocol+"//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+this.type+"?"+OpenLayers.Util.getParameterString(a),b=document.createElement("script");b.type="text/javascript";b.src=a;b.id=this._callbackId;document.getElementsByTagName("head")[0].appendChild(b)},
2337 initLayer:function(){var a=this.metadata.resourceSets[0].resources[0],b=a.imageUrl.replace("{quadkey}","${quadkey}"),b=b.replace("{culture}",this.culture),b=b.replace(this.protocolRegex,this.protocol);this.url=[];for(var c=0;c<a.imageUrlSubdomains.length;++c)this.url.push(b.replace("{subdomain}",a.imageUrlSubdomains[c]));this.addOptions({maxResolution:Math.min(this.serverResolutions[a.zoomMin],this.maxResolution||Number.POSITIVE_INFINITY),numZoomLevels:Math.min(a.zoomMax+1-a.zoomMin,this.numZoomLevels)},
2338 !0);this.isBaseLayer||this.redraw();this.updateAttribution()},getURL:function(a){if(this.url){var b=this.getXYZ(a);a=b.x;for(var c=b.y,b=b.z,d=[],e=b;0<e;--e){var f="0",g=1<<e-1;0!=(a&g)&&f++;0!=(c&g)&&(f++,f++);d.push(f)}d=d.join("");a=this.selectUrl(""+a+c+b,this.url);return OpenLayers.String.format(a,{quadkey:d})}},updateAttribution:function(){var a=this.metadata;if(a.resourceSets&&this.map&&this.map.center){var b=a.resourceSets[0].resources[0],c=this.map.getExtent().transform(this.map.getProjectionObject(),
2339 new OpenLayers.Projection("EPSG:4326")),d=b.imageryProviders||[],e=OpenLayers.Util.indexOf(this.serverResolutions,this.getServerResolution()),b="",f,g,h,k,l,m,n;g=0;for(h=d.length;g<h;++g)for(f=d[g],k=0,l=f.coverageAreas.length;k<l;++k)n=f.coverageAreas[k],m=OpenLayers.Bounds.fromArray(n.bbox,!0),c.intersectsBounds(m)&&(e<=n.zoomMax&&e>=n.zoomMin)&&(b+=f.attribution+" ");a=a.brandLogoUri.replace(this.protocolRegex,this.protocol);this.attribution=OpenLayers.String.format(this.attributionTemplate,{type:this.type.toLowerCase(),
2340 logo:a,copyrights:b});this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"attribution"})}},setMap:function(){OpenLayers.Layer.XYZ.prototype.setMap.apply(this,arguments);this.map.events.register("moveend",this,this.updateAttribution)},clone:function(a){null==a&&(a=new OpenLayers.Layer.Bing(this.options));return a=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[a])},destroy:function(){this.map&&this.map.events.unregister("moveend",this,this.updateAttribution);OpenLayers.Layer.XYZ.prototype.destroy.apply(this,
2341 arguments)},CLASS_NAME:"OpenLayers.Layer.Bing"});OpenLayers.Layer.Bing.processMetadata=function(a){this.metadata=a;this.initLayer();a=document.getElementById(this._callbackId);a.parentNode.removeChild(a);window[this._callbackId]=void 0;delete this._callbackId};OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:!0,initialize:function(a,b){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),select:new OpenLayers.Style(OpenLayers.Feature.Vector.style.select),temporary:new OpenLayers.Style(OpenLayers.Feature.Vector.style.temporary),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(a instanceof OpenLayers.Style)this.styles["default"]=a,this.styles.select=a,this.styles.temporary=a,this.styles["delete"]=
2342 a;else if("object"==typeof a)for(var c in a)if(a[c]instanceof OpenLayers.Style)this.styles[c]=a[c];else if("object"==typeof a[c])this.styles[c]=new OpenLayers.Style(a[c]);else{this.styles["default"]=new OpenLayers.Style(a);this.styles.select=new OpenLayers.Style(a);this.styles.temporary=new OpenLayers.Style(a);this.styles["delete"]=new OpenLayers.Style(a);break}OpenLayers.Util.extend(this,b)},destroy:function(){for(var a in this.styles)this.styles[a].destroy();this.styles=null},createSymbolizer:function(a,
2343 b){a||(a=new OpenLayers.Feature.Vector);this.styles[b]||(b="default");a.renderIntent=b;var c={};this.extendDefault&&"default"!=b&&(c=this.styles["default"].createSymbolizer(a));return OpenLayers.Util.extend(c,this.styles[b].createSymbolizer(a))},addUniqueValueRules:function(a,b,c,d){var e=[],f;for(f in c)e.push(new OpenLayers.Rule({symbolizer:c[f],context:d,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:b,value:f})}));this.styles[a].addRules(e)},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:!1,isFixed:!1,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:!0,style:null,styleMap:null,strategies:null,protocol:null,renderers:["SVG","VML","Canvas"],renderer:null,rendererOptions:null,geometryType:null,drawn:!1,ratio:1,initialize:function(a,b){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.renderer&&this.renderer.supported()||this.assignRenderer();this.renderer&&this.renderer.supported()||
2344 (this.renderer=null,this.displayError());this.styleMap||(this.styleMap=new OpenLayers.StyleMap);this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies)for(var c=0,d=this.strategies.length;c<d;c++)this.strategies[c].setLayer(this)},destroy:function(){if(this.strategies){var a,b,c;b=0;for(c=this.strategies.length;b<c;b++)a=this.strategies[b],a.autoDestroy&&a.destroy();this.strategies=null}this.protocol&&(this.protocol.autoDestroy&&this.protocol.destroy(),this.protocol=
2345 null);this.destroyFeatures();this.unrenderedFeatures=this.selectedFeatures=this.features=null;this.renderer&&this.renderer.destroy();this.drawn=this.geometryType=this.renderer=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments)},clone:function(a){null==a&&(a=new OpenLayers.Layer.Vector(this.name,this.getOptions()));a=OpenLayers.Layer.prototype.clone.apply(this,[a]);for(var b=this.features,c=b.length,d=Array(c),e=0;e<c;++e)d[e]=b[e].clone();a.features=d;return a},refresh:function(a){this.calculateInRange()&&
2346 this.visibility&&this.events.triggerEvent("refresh",a)},assignRenderer:function(){for(var a=0,b=this.renderers.length;a<b;a++){var c=this.renderers[a];if((c="function"==typeof c?c:OpenLayers.Renderer[c])&&c.prototype.supported()){this.renderer=new c(this.div,this.rendererOptions);break}}},displayError:function(){this.reportError&&OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",{renderers:this.renderers.join("\n")}))},setMap:function(a){OpenLayers.Layer.prototype.setMap.apply(this,
2347 arguments);if(this.renderer){this.renderer.map=this.map;var b=this.map.getSize();b.w*=this.ratio;b.h*=this.ratio;this.renderer.setSize(b)}else this.map.removeLayer(this)},afterAdd:function(){if(this.strategies){var a,b,c;b=0;for(c=this.strategies.length;b<c;b++)a=this.strategies[b],a.autoActivate&&a.activate()}},removeMap:function(a){this.drawn=!1;if(this.strategies){var b,c;b=0;for(c=this.strategies.length;b<c;b++)a=this.strategies[b],a.autoActivate&&a.deactivate()}},onMapResize:function(){OpenLayers.Layer.prototype.onMapResize.apply(this,
2348 arguments);var a=this.map.getSize();a.w*=this.ratio;a.h*=this.ratio;this.renderer.setSize(a)},moveTo:function(a,b,c){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var d=!0;if(!c){this.renderer.root.style.visibility="hidden";var d=this.map.getSize(),e=d.w,d=d.h,e=e/2*this.ratio-e/2,d=d/2*this.ratio-d/2,e=e+this.map.layerContainerOriginPx.x,e=-Math.round(e),d=d+this.map.layerContainerOriginPx.y,d=-Math.round(d);this.div.style.left=e+"px";this.div.style.top=d+"px";e=this.map.getExtent().scale(this.ratio);
2349 d=this.renderer.setExtent(e,b);this.renderer.root.style.visibility="visible";!0===OpenLayers.IS_GECKO&&(this.div.scrollLeft=this.div.scrollLeft);if(!b&&d)for(var f in this.unrenderedFeatures)e=this.unrenderedFeatures[f],this.drawFeature(e)}if(!this.drawn||b||!d)for(this.drawn=!0,f=0,d=this.features.length;f<d;f++)this.renderer.locked=f!==d-1,e=this.features[f],this.drawFeature(e)},display:function(a){OpenLayers.Layer.prototype.display.apply(this,arguments);var b=this.div.style.display;b!=this.renderer.root.style.display&&
2350 (this.renderer.root.style.display=b)},addFeatures:function(a,b){OpenLayers.Util.isArray(a)||(a=[a]);var c=!b||!b.silent;if(c){var d={features:a};if(!1===this.events.triggerEvent("beforefeaturesadded",d))return;a=d.features}for(var d=[],e=0,f=a.length;e<f;e++){this.renderer.locked=e!=a.length-1?!0:!1;var g=a[e];if(this.geometryType&&!(g.geometry instanceof this.geometryType))throw new TypeError("addFeatures: component should be an "+this.geometryType.prototype.CLASS_NAME);g.layer=this;!g.style&&this.style&&
2351 (g.style=OpenLayers.Util.extend({},this.style));if(c){if(!1===this.events.triggerEvent("beforefeatureadded",{feature:g}))continue;this.preFeatureInsert(g)}d.push(g);this.features.push(g);this.drawFeature(g);c&&(this.events.triggerEvent("featureadded",{feature:g}),this.onFeatureInsert(g))}c&&this.events.triggerEvent("featuresadded",{features:d})},removeFeatures:function(a,b){if(a&&0!==a.length){if(a===this.features)return this.removeAllFeatures(b);OpenLayers.Util.isArray(a)||(a=[a]);a===this.selectedFeatures&&
2352 (a=a.slice());var c=!b||!b.silent;c&&this.events.triggerEvent("beforefeaturesremoved",{features:a});for(var d=a.length-1;0<=d;d--){this.renderer.locked=0!=d&&a[d-1].geometry?!0:!1;var e=a[d];delete this.unrenderedFeatures[e.id];c&&this.events.triggerEvent("beforefeatureremoved",{feature:e});this.features=OpenLayers.Util.removeItem(this.features,e);e.layer=null;e.geometry&&this.renderer.eraseFeatures(e);-1!=OpenLayers.Util.indexOf(this.selectedFeatures,e)&&OpenLayers.Util.removeItem(this.selectedFeatures,
2353 e);c&&this.events.triggerEvent("featureremoved",{feature:e})}c&&this.events.triggerEvent("featuresremoved",{features:a})}},removeAllFeatures:function(a){a=!a||!a.silent;var b=this.features;a&&this.events.triggerEvent("beforefeaturesremoved",{features:b});for(var c,d=b.length-1;0<=d;d--)c=b[d],a&&this.events.triggerEvent("beforefeatureremoved",{feature:c}),c.layer=null,a&&this.events.triggerEvent("featureremoved",{feature:c});this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=
2354 [];a&&this.events.triggerEvent("featuresremoved",{features:b})},destroyFeatures:function(a,b){void 0==a&&(a=this.features);if(a){this.removeFeatures(a,b);for(var c=a.length-1;0<=c;c--)a[c].destroy()}},drawFeature:function(a,b){if(this.drawn){if("object"!=typeof b){b||a.state!==OpenLayers.State.DELETE||(b="delete");var c=b||a.renderIntent;(b=a.style||this.style)||(b=this.styleMap.createSymbolizer(a,c))}c=this.renderer.drawFeature(a,b);!1===c||null===c?this.unrenderedFeatures[a.id]=a:delete this.unrenderedFeatures[a.id]}},
2355 eraseFeatures:function(a){this.renderer.eraseFeatures(a)},getFeatureFromEvent:function(a){if(!this.renderer)throw Error("getFeatureFromEvent called on layer with no renderer. This usually means you destroyed a layer, but not some handler which is associated with it.");var b=null;(a=this.renderer.getFeatureIdFromEvent(a))&&(b="string"===typeof a?this.getFeatureById(a):a);return b},getFeatureBy:function(a,b){for(var c=null,d=0,e=this.features.length;d<e;++d)if(this.features[d][a]==b){c=this.features[d];
2356 break}return c},getFeatureById:function(a){return this.getFeatureBy("id",a)},getFeatureByFid:function(a){return this.getFeatureBy("fid",a)},getFeaturesByAttribute:function(a,b){var c,d,e=this.features.length,f=[];for(c=0;c<e;c++)(d=this.features[c])&&d.attributes&&d.attributes[a]===b&&f.push(d);return f},onFeatureInsert:function(a){},preFeatureInsert:function(a){},getDataExtent:function(){var a=null,b=this.features;if(b&&0<b.length)for(var c=null,d=0,e=b.length;d<e;d++)if(c=b[d].geometry)null===a&&
2357 (a=new OpenLayers.Bounds),a.extend(c.getBounds());return a},CLASS_NAME:"OpenLayers.Layer.Vector"});OpenLayers.Layer.PointGrid=OpenLayers.Class(OpenLayers.Layer.Vector,{dx:null,dy:null,ratio:1.5,maxFeatures:250,rotation:0,origin:null,gridBounds:null,initialize:function(a){a=a||{};OpenLayers.Layer.Vector.prototype.initialize.apply(this,[a.name,a])},setMap:function(a){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);a.events.register("moveend",this,this.onMoveEnd)},removeMap:function(a){a.events.unregister("moveend",this,this.onMoveEnd);OpenLayers.Layer.Vector.prototype.removeMap.apply(this,
2358 arguments)},setRatio:function(a){this.ratio=a;this.updateGrid(!0)},setMaxFeatures:function(a){this.maxFeatures=a;this.updateGrid(!0)},setSpacing:function(a,b){this.dx=a;this.dy=b||a;this.updateGrid(!0)},setOrigin:function(a){this.origin=a;this.updateGrid(!0)},getOrigin:function(){this.origin||(this.origin=this.map.getExtent().getCenterLonLat());return this.origin},setRotation:function(a){this.rotation=a;this.updateGrid(!0)},onMoveEnd:function(){this.updateGrid()},getViewBounds:function(){var a=this.map.getExtent();
2359 if(this.rotation){var b=this.getOrigin(),b=new OpenLayers.Geometry.Point(b.lon,b.lat),a=a.toGeometry();a.rotate(-this.rotation,b);a=a.getBounds()}return a},updateGrid:function(a){if(a||this.invalidBounds()){var b=this.getViewBounds(),c=this.getOrigin();a=new OpenLayers.Geometry.Point(c.lon,c.lat);var d=b.getWidth(),e=b.getHeight(),f=d/e,g=Math.sqrt(this.dx*this.dy*this.maxFeatures/f),d=Math.min(d*this.ratio,g*f),e=Math.min(e*this.ratio,g),b=b.getCenterLonLat();this.gridBounds=new OpenLayers.Bounds(b.lon-
2360 d/2,b.lat-e/2,b.lon+d/2,b.lat+e/2);for(var b=Math.floor(e/this.dy),d=Math.floor(d/this.dx),e=c.lon+this.dx*Math.ceil((this.gridBounds.left-c.lon)/this.dx),c=c.lat+this.dy*Math.ceil((this.gridBounds.bottom-c.lat)/this.dy),g=Array(b*d),h,k=0;k<d;++k)for(var f=e+k*this.dx,l=0;l<b;++l)h=c+l*this.dy,h=new OpenLayers.Geometry.Point(f,h),this.rotation&&h.rotate(this.rotation,a),g[k*b+l]=new OpenLayers.Feature.Vector(h);this.destroyFeatures(this.features,{silent:!0});this.addFeatures(g,{silent:!0})}},invalidBounds:function(){return!this.gridBounds||
2361 !this.gridBounds.containsBounds(this.getViewBounds())},CLASS_NAME:"OpenLayers.Layer.PointGrid"});OpenLayers.Handler.MouseWheel=OpenLayers.Class(OpenLayers.Handler,{wheelListener:null,interval:0,maxDelta:Number.POSITIVE_INFINITY,delta:0,cumulative:!0,initialize:function(a,b,c){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.wheelListener=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this)},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.wheelListener=null},onWheelEvent:function(a){if(this.map&&this.checkModifiers(a)){for(var b=
2362 !1,c=!1,d=!1,e=OpenLayers.Event.element(a);null!=e&&!d&&!b;){if(!b)try{var f,b=(f=e.currentStyle?e.currentStyle.overflow:document.defaultView.getComputedStyle(e,null).getPropertyValue("overflow"))&&"auto"==f||"scroll"==f}catch(g){}if(!c&&(c=OpenLayers.Element.hasClass(e,"olScrollable"),!c))for(var d=0,h=this.map.layers.length;d<h;d++){var k=this.map.layers[d];if(e==k.div||e==k.pane){c=!0;break}}d=e==this.map.div;e=e.parentNode}if(!b&&d){if(c)if(b=0,a.wheelDelta?(b=a.wheelDelta,0===b%160&&(b*=0.75),
2363 b/=120):a.detail&&(b=-(a.detail/Math.abs(a.detail))),this.delta+=b,window.clearTimeout(this._timeoutId),this.interval&&Math.abs(this.delta)<this.maxDelta){var l=OpenLayers.Util.extend({},a);this._timeoutId=window.setTimeout(OpenLayers.Function.bind(function(){this.wheelZoom(l)},this),this.interval)}else this.wheelZoom(a);OpenLayers.Event.stop(a)}}},wheelZoom:function(a){var b=this.delta;this.delta=0;b&&(a.xy=this.map.events.getMousePosition(a),0>b?this.callback("down",[a,this.cumulative?Math.max(-this.maxDelta,
2364 b):-1]):this.callback("up",[a,this.cumulative?Math.min(this.maxDelta,b):1]))},activate:function(a){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var b=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",b);OpenLayers.Event.observe(window,"mousewheel",b);OpenLayers.Event.observe(document,"mousewheel",b);return!0}return!1},deactivate:function(a){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var b=this.wheelListener;OpenLayers.Event.stopObserving(window,
2365 "DOMMouseScroll",b);OpenLayers.Event.stopObserving(window,"mousewheel",b);OpenLayers.Event.stopObserving(document,"mousewheel",b);return!0}return!1},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Symbolizer=OpenLayers.Class({zIndex:0,initialize:function(a){OpenLayers.Util.extend(this,a)},clone:function(){return new (eval(this.CLASS_NAME))(OpenLayers.Util.extend({},this))},CLASS_NAME:"OpenLayers.Symbolizer"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:!1,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(a){this.symbolizer={};OpenLayers.Util.extend(this,a);this.symbolizers&&delete this.symbolizer;this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){for(var a in this.symbolizer)this.symbolizer[a]=null;this.symbolizer=null;delete this.symbolizers},evaluate:function(a){var b=
2366 this.getContext(a),c=!0;if(this.minScaleDenominator||this.maxScaleDenominator)var d=a.layer.map.getScale();this.minScaleDenominator&&(c=d>=OpenLayers.Style.createLiteral(this.minScaleDenominator,b));c&&this.maxScaleDenominator&&(c=d<OpenLayers.Style.createLiteral(this.maxScaleDenominator,b));c&&this.filter&&(c="OpenLayers.Filter.FeatureId"==this.filter.CLASS_NAME?this.filter.evaluate(a):this.filter.evaluate(b));return c},getContext:function(a){var b=this.context;b||(b=a.attributes||a.data);"function"==
2367 typeof this.context&&(b=this.context(a));return b},clone:function(){var a=OpenLayers.Util.extend({},this);if(this.symbolizers){var b=this.symbolizers.length;a.symbolizers=Array(b);for(var c=0;c<b;++c)a.symbolizers[c]=this.symbolizers[c].clone()}else{a.symbolizer={};for(var d in this.symbolizer)b=this.symbolizer[d],c=typeof b,"object"===c?a.symbolizer[d]=OpenLayers.Util.extend({},b):"string"===c&&(a.symbolizer[d]=b)}a.filter=this.filter&&this.filter.clone();a.context=this.context&&OpenLayers.Util.extend({},
2368 this.context);return new OpenLayers.Rule(a)},CLASS_NAME:"OpenLayers.Rule"});OpenLayers.Format.SLD=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{profile:null,defaultVersion:"1.0.0",stringifyOutput:!0,namedLayersAsArray:!1,CLASS_NAME:"OpenLayers.Format.SLD"});OpenLayers.Symbolizer.Polygon=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Polygon"});OpenLayers.Format.GML.v2=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",initialize:function(a){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[a])},readers:{gml:OpenLayers.Util.applyDefaults({outerBoundaryIs:function(a,b){var c={};this.readChildNodes(a,c);b.outer=c.components[0]},innerBoundaryIs:function(a,b){var c={};this.readChildNodes(a,c);b.inner.push(c.components[0])},Box:function(a,b){var c=
2369 {};this.readChildNodes(a,c);b.components||(b.components=[]);var d=c.points[0],c=c.points[1];b.components.push(new OpenLayers.Bounds(d.x,d.y,c.x,c.y))}},OpenLayers.Format.GML.Base.prototype.readers.gml),feature:OpenLayers.Format.GML.Base.prototype.readers.feature,wfs:OpenLayers.Format.GML.Base.prototype.readers.wfs},write:function(a){var b;b=OpenLayers.Util.isArray(a)?"wfs:FeatureCollection":"gml:featureMember";a=this.writeNode(b,a);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);
2370 return OpenLayers.Format.XML.prototype.write.apply(this,[a])},writers:{gml:OpenLayers.Util.applyDefaults({Point:function(a){var b=this.createElementNSPlus("gml:Point");this.writeNode("coordinates",[a],b);return b},coordinates:function(a){for(var b=a.length,c=Array(b),d,e=0;e<b;++e)d=a[e],c[e]=this.xy?d.x+","+d.y:d.y+","+d.x,void 0!=d.z&&(c[e]+=","+d.z);return this.createElementNSPlus("gml:coordinates",{attributes:{decimal:".",cs:",",ts:" "},value:1==b?c[0]:c.join(" ")})},LineString:function(a){var b=
2371 this.createElementNSPlus("gml:LineString");this.writeNode("coordinates",a.components,b);return b},Polygon:function(a){var b=this.createElementNSPlus("gml:Polygon");this.writeNode("outerBoundaryIs",a.components[0],b);for(var c=1;c<a.components.length;++c)this.writeNode("innerBoundaryIs",a.components[c],b);return b},outerBoundaryIs:function(a){var b=this.createElementNSPlus("gml:outerBoundaryIs");this.writeNode("LinearRing",a,b);return b},innerBoundaryIs:function(a){var b=this.createElementNSPlus("gml:innerBoundaryIs");
2372 this.writeNode("LinearRing",a,b);return b},LinearRing:function(a){var b=this.createElementNSPlus("gml:LinearRing");this.writeNode("coordinates",a.components,b);return b},Box:function(a){var b=this.createElementNSPlus("gml:Box");this.writeNode("coordinates",[{x:a.left,y:a.bottom},{x:a.right,y:a.top}],b);this.srsName&&b.setAttribute("srsName",this.srsName);return b}},OpenLayers.Format.GML.Base.prototype.writers.gml),feature:OpenLayers.Format.GML.Base.prototype.writers.feature,wfs:OpenLayers.Format.GML.Base.prototype.writers.wfs},
2373 CLASS_NAME:"OpenLayers.Format.GML.v2"});OpenLayers.Format.Filter.v1_0_0=OpenLayers.Class(OpenLayers.Format.GML.v2,OpenLayers.Format.Filter.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.0.0/filter.xsd",initialize:function(a){OpenLayers.Format.GML.v2.prototype.initialize.apply(this,[a])},readers:{ogc:OpenLayers.Util.applyDefaults({PropertyIsEqualTo:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsNotEqualTo:function(a,
2374 b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO});this.readChildNodes(a,c);b.filters.push(c)},PropertyIsLike:function(a,b){var c=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(a,c);var d=a.getAttribute("wildCard"),e=a.getAttribute("singleChar"),f=a.getAttribute("escape");c.value2regex(d,e,f);b.filters.push(c)}},OpenLayers.Format.Filter.v1.prototype.readers.ogc),gml:OpenLayers.Format.GML.v2.prototype.readers.gml,
2375 feature:OpenLayers.Format.GML.v2.prototype.readers.feature},writers:{ogc:OpenLayers.Util.applyDefaults({PropertyIsEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsEqualTo");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsNotEqualTo:function(a){var b=this.createElementNSPlus("ogc:PropertyIsNotEqualTo");this.writeNode("PropertyName",a,b);this.writeOgcExpression(a.value,b);return b},PropertyIsLike:function(a){var b=this.createElementNSPlus("ogc:PropertyIsLike",
2376 {attributes:{wildCard:"*",singleChar:".",escape:"!"}});this.writeNode("PropertyName",a,b);this.writeNode("Literal",a.regex2value(),b);return b},BBOX:function(a){var b=this.createElementNSPlus("ogc:BBOX");a.property&&this.writeNode("PropertyName",a,b);var c=this.writeNode("gml:Box",a.value,b);a.projection&&c.setAttribute("srsName",a.projection);return b}},OpenLayers.Format.Filter.v1.prototype.writers.ogc),gml:OpenLayers.Format.GML.v2.prototype.writers.gml,feature:OpenLayers.Format.GML.v2.prototype.writers.feature},
2377 writeSpatial:function(a,b){var c=this.createElementNSPlus("ogc:"+b);this.writeNode("PropertyName",a,c);if(a.value instanceof OpenLayers.Filter.Function)this.writeNode("Function",a.value,c);else{var d;d=a.value instanceof OpenLayers.Geometry?this.writeNode("feature:_geometry",a.value).firstChild:this.writeNode("gml:Box",a.value);a.projection&&d.setAttribute("srsName",a.projection);c.appendChild(d)}return c},CLASS_NAME:"OpenLayers.Format.Filter.v1_0_0"});OpenLayers.Format.WFST.v1_0_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,OpenLayers.Format.WFST.v1,{version:"1.0.0",srsNameInQuery:!1,schemaLocations:{wfs:"http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"},initialize:function(a){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[a]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[a])},readNode:function(a,b,c){return OpenLayers.Format.GML.v2.prototype.readNode.apply(this,arguments)},readers:{wfs:OpenLayers.Util.applyDefaults({WFS_TransactionResponse:function(a,
2378 b){b.insertIds=[];b.success=!1;this.readChildNodes(a,b)},InsertResult:function(a,b){var c={fids:[]};this.readChildNodes(a,c);b.insertIds=b.insertIds.concat(c.fids)},TransactionResult:function(a,b){this.readChildNodes(a,b)},Status:function(a,b){this.readChildNodes(a,b)},SUCCESS:function(a,b){b.success=!0}},OpenLayers.Format.WFST.v1.prototype.readers.wfs),gml:OpenLayers.Format.GML.v2.prototype.readers.gml,feature:OpenLayers.Format.GML.v2.prototype.readers.feature,ogc:OpenLayers.Format.Filter.v1_0_0.prototype.readers.ogc},
2379 writers:{wfs:OpenLayers.Util.applyDefaults({Query:function(a){a=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName,srsNameInQuery:this.srsNameInQuery},a);var b=a.featurePrefix,c=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(b?b+":":"")+a.featureType}});a.srsNameInQuery&&a.srsName&&c.setAttribute("srsName",a.srsName);a.featureNS&&c.setAttribute("xmlns:"+b,a.featureNS);if(a.propertyNames)for(var b=0,d=a.propertyNames.length;b<
2380 d;b++)this.writeNode("ogc:PropertyName",{property:a.propertyNames[b]},c);a.filter&&(this.setFilterProperty(a.filter),this.writeNode("ogc:Filter",a.filter,c));return c}},OpenLayers.Format.WFST.v1.prototype.writers.wfs),gml:OpenLayers.Format.GML.v2.prototype.writers.gml,feature:OpenLayers.Format.GML.v2.prototype.writers.feature,ogc:OpenLayers.Format.Filter.v1_0_0.prototype.writers.ogc},CLASS_NAME:"OpenLayers.Format.WFST.v1_0_0"});OpenLayers.ElementsIndexer=OpenLayers.Class({maxZIndex:null,order:null,indices:null,compare:null,initialize:function(a){this.compare=a?OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER:OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;this.clear()},insert:function(a){this.exists(a)&&this.remove(a);var b=a.id;this.determineZIndex(a);for(var c=-1,d=this.order.length,e;1<d-c;)e=parseInt((c+d)/2),0<this.compare(this,a,OpenLayers.Util.getElement(this.order[e]))?c=e:d=e;this.order.splice(d,
2381 0,b);this.indices[b]=this.getZIndex(a);return this.getNextElement(d)},remove:function(a){a=a.id;var b=OpenLayers.Util.indexOf(this.order,a);0<=b&&(this.order.splice(b,1),delete this.indices[a],this.maxZIndex=0<this.order.length?this.indices[this.order[this.order.length-1]]:0)},clear:function(){this.order=[];this.indices={};this.maxZIndex=0},exists:function(a){return null!=this.indices[a.id]},getZIndex:function(a){return a._style.graphicZIndex},determineZIndex:function(a){var b=a._style.graphicZIndex;
2382 null==b?(b=this.maxZIndex,a._style.graphicZIndex=b):b>this.maxZIndex&&(this.maxZIndex=b)},getNextElement:function(a){a+=1;if(a<this.order.length){var b=OpenLayers.Util.getElement(this.order[a]);void 0==b&&(b=this.getNextElement(a));return b}return null},CLASS_NAME:"OpenLayers.ElementsIndexer"});
2383 OpenLayers.ElementsIndexer.IndexingMethods={Z_ORDER:function(a,b,c){b=a.getZIndex(b);var d=0;c&&(a=a.getZIndex(c),d=b-a);return d},Z_ORDER_DRAWING_ORDER:function(a,b,c){a=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(a,b,c);c&&0==a&&(a=1);return a},Z_ORDER_Y_ORDER:function(a,b,c){a=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(a,b,c);c&&0===a&&(b=c._boundsBottom-b._boundsBottom,a=0===b?1:b);return a}};
2384 OpenLayers.Renderer.Elements=OpenLayers.Class(OpenLayers.Renderer,{rendererRoot:null,root:null,vectorRoot:null,textRoot:null,xmlns:null,xOffset:0,indexer:null,BACKGROUND_ID_SUFFIX:"_background",LABEL_ID_SUFFIX:"_label",LABEL_OUTLINE_SUFFIX:"_outline",initialize:function(a,b){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.rendererRoot=this.createRenderRoot();this.root=this.createRoot("_root");this.vectorRoot=this.createRoot("_vroot");this.textRoot=this.createRoot("_troot");this.root.appendChild(this.vectorRoot);
2385 this.root.appendChild(this.textRoot);this.rendererRoot.appendChild(this.root);this.container.appendChild(this.rendererRoot);b&&(b.zIndexing||b.yOrdering)&&(this.indexer=new OpenLayers.ElementsIndexer(b.yOrdering))},destroy:function(){this.clear();this.xmlns=this.root=this.rendererRoot=null;OpenLayers.Renderer.prototype.destroy.apply(this,arguments)},clear:function(){var a,b=this.vectorRoot;if(b)for(;a=b.firstChild;)b.removeChild(a);if(b=this.textRoot)for(;a=b.firstChild;)b.removeChild(a);this.indexer&&
2386 this.indexer.clear()},setExtent:function(a,b){var c=OpenLayers.Renderer.prototype.setExtent.apply(this,arguments),d=this.getResolution();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var e,f=a.getWidth()/this.map.getExtent().getWidth();a=a.scale(1/f);f=this.map.getMaxExtent();f.right>a.left&&f.right<a.right?e=!0:f.left>a.left&&f.left<a.right&&(e=!1);if(e!==this.rightOfDateLine||b)c=!1,this.xOffset=!0===e?f.getWidth()/d:0;this.rightOfDateLine=e}return c},getNodeType:function(a,b){},drawGeometry:function(a,
2387 b,c){var d=a.CLASS_NAME,e=!0;if("OpenLayers.Geometry.Collection"==d||"OpenLayers.Geometry.MultiPoint"==d||"OpenLayers.Geometry.MultiLineString"==d||"OpenLayers.Geometry.MultiPolygon"==d){for(var d=0,f=a.components.length;d<f;d++)e=this.drawGeometry(a.components[d],b,c)&&e;return e}d=e=!1;"none"!=b.display&&(b.backgroundGraphic?this.redrawBackgroundNode(a.id,a,b,c):d=!0,e=this.redrawNode(a.id,a,b,c));!1==e&&(b=document.getElementById(a.id))&&(b._style.backgroundGraphic&&(d=!0),b.parentNode.removeChild(b));
2388 d&&(b=document.getElementById(a.id+this.BACKGROUND_ID_SUFFIX))&&b.parentNode.removeChild(b);return e},redrawNode:function(a,b,c,d){c=this.applyDefaultSymbolizer(c);a=this.nodeFactory(a,this.getNodeType(b,c));a._featureId=d;a._boundsBottom=b.getBounds().bottom;a._geometryClass=b.CLASS_NAME;a._style=c;b=this.drawGeometryNode(a,b,c);if(!1===b)return!1;a=b.node;this.indexer?(c=this.indexer.insert(a))?this.vectorRoot.insertBefore(a,c):this.vectorRoot.appendChild(a):a.parentNode!==this.vectorRoot&&this.vectorRoot.appendChild(a);
2389 this.postDraw(a);return b.complete},redrawBackgroundNode:function(a,b,c,d){c=OpenLayers.Util.extend({},c);c.externalGraphic=c.backgroundGraphic;c.graphicXOffset=c.backgroundXOffset;c.graphicYOffset=c.backgroundYOffset;c.graphicZIndex=c.backgroundGraphicZIndex;c.graphicWidth=c.backgroundWidth||c.graphicWidth;c.graphicHeight=c.backgroundHeight||c.graphicHeight;c.backgroundGraphic=null;c.backgroundXOffset=null;c.backgroundYOffset=null;c.backgroundGraphicZIndex=null;return this.redrawNode(a+this.BACKGROUND_ID_SUFFIX,
2390 b,c,null)},drawGeometryNode:function(a,b,c){c=c||a._style;var d={isFilled:void 0===c.fill?!0:c.fill,isStroked:void 0===c.stroke?!!c.strokeWidth:c.stroke},e;switch(b.CLASS_NAME){case "OpenLayers.Geometry.Point":!1===c.graphic&&(d.isFilled=!1,d.isStroked=!1);e=this.drawPoint(a,b);break;case "OpenLayers.Geometry.LineString":d.isFilled=!1;e=this.drawLineString(a,b);break;case "OpenLayers.Geometry.LinearRing":e=this.drawLinearRing(a,b);break;case "OpenLayers.Geometry.Polygon":e=this.drawPolygon(a,b);break;
2391 case "OpenLayers.Geometry.Rectangle":e=this.drawRectangle(a,b)}a._options=d;return!1!=e?{node:this.setStyle(a,c,d,b),complete:e}:!1},postDraw:function(a){},drawPoint:function(a,b){},drawLineString:function(a,b){},drawLinearRing:function(a,b){},drawPolygon:function(a,b){},drawRectangle:function(a,b){},drawCircle:function(a,b){},removeText:function(a){var b=document.getElementById(a+this.LABEL_ID_SUFFIX);b&&this.textRoot.removeChild(b);(a=document.getElementById(a+this.LABEL_OUTLINE_SUFFIX))&&this.textRoot.removeChild(a)},
2392 getFeatureIdFromEvent:function(a){var b=a.target,c=b&&b.correspondingUseElement;return(c?c:b||a.srcElement)._featureId},eraseGeometry:function(a,b){if("OpenLayers.Geometry.MultiPoint"==a.CLASS_NAME||"OpenLayers.Geometry.MultiLineString"==a.CLASS_NAME||"OpenLayers.Geometry.MultiPolygon"==a.CLASS_NAME||"OpenLayers.Geometry.Collection"==a.CLASS_NAME)for(var c=0,d=a.components.length;c<d;c++)this.eraseGeometry(a.components[c],b);else(c=OpenLayers.Util.getElement(a.id))&&c.parentNode&&(c.geometry&&(c.geometry.destroy(),
2393 c.geometry=null),c.parentNode.removeChild(c),this.indexer&&this.indexer.remove(c),c._style.backgroundGraphic&&(c=OpenLayers.Util.getElement(a.id+this.BACKGROUND_ID_SUFFIX))&&c.parentNode&&c.parentNode.removeChild(c))},nodeFactory:function(a,b){var c=OpenLayers.Util.getElement(a);c?this.nodeTypeCompare(c,b)||(c.parentNode.removeChild(c),c=this.nodeFactory(a,b)):c=this.createNode(b,a);return c},nodeTypeCompare:function(a,b){},createNode:function(a,b){},moveRoot:function(a){var b=this.root;a.root.parentNode==
2394 this.rendererRoot&&(b=a.root);b.parentNode.removeChild(b);a.rendererRoot.appendChild(b)},getRenderLayerId:function(){return this.root.parentNode.parentNode.id},isComplexSymbol:function(a){return"circle"!=a&&!!a},CLASS_NAME:"OpenLayers.Renderer.Elements"});OpenLayers.Control.ArgParser=OpenLayers.Class(OpenLayers.Control,{center:null,zoom:null,layers:null,displayProjection:null,getParameters:function(a){a=a||window.location.href;var b=OpenLayers.Util.getParameters(a),c=a.indexOf("#");0<c&&(a="?"+a.substring(c+1,a.length),OpenLayers.Util.extend(b,OpenLayers.Util.getParameters(a)));return b},setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var b=0,c=this.map.controls.length;b<c;b++){var d=this.map.controls[b];if(d!=this&&
2395 "OpenLayers.Control.ArgParser"==d.CLASS_NAME){d.displayProjection!=this.displayProjection&&(this.displayProjection=d.displayProjection);break}}b==this.map.controls.length&&(b=this.getParameters(),b.layers&&(this.layers=b.layers,this.map.events.register("addlayer",this,this.configureLayers),this.configureLayers()),b.lat&&b.lon&&(this.center=new OpenLayers.LonLat(parseFloat(b.lon),parseFloat(b.lat)),b.zoom&&(this.zoom=parseFloat(b.zoom)),this.map.events.register("changebaselayer",this,this.setCenter),
2396 this.setCenter()))},setCenter:function(){this.map.baseLayer&&(this.map.events.unregister("changebaselayer",this,this.setCenter),this.displayProjection&&this.center.transform(this.displayProjection,this.map.getProjectionObject()),this.map.setCenter(this.center,this.zoom))},configureLayers:function(){if(this.layers.length==this.map.layers.length){this.map.events.unregister("addlayer",this,this.configureLayers);for(var a=0,b=this.layers.length;a<b;a++){var c=this.map.layers[a],d=this.layers.charAt(a);
2397 "B"==d?this.map.setBaseLayer(c):"T"!=d&&"F"!=d||c.setVisibility("T"==d)}}},CLASS_NAME:"OpenLayers.Control.ArgParser"});OpenLayers.Control.Permalink=OpenLayers.Class(OpenLayers.Control,{argParserClass:OpenLayers.Control.ArgParser,element:null,anchor:!1,base:"",displayProjection:null,initialize:function(a,b,c){null===a||"object"!=typeof a||OpenLayers.Util.isElement(a)?(OpenLayers.Control.prototype.initialize.apply(this,[c]),this.element=OpenLayers.Util.getElement(a),this.base=b||document.location.href):(this.base=document.location.href,OpenLayers.Control.prototype.initialize.apply(this,[a]),null!=this.element&&(this.element=
2398 OpenLayers.Util.getElement(this.element)))},destroy:function(){this.element&&this.element.parentNode==this.div&&(this.div.removeChild(this.element),this.element=null);this.map&&this.map.events.unregister("moveend",this,this.updateLink);OpenLayers.Control.prototype.destroy.apply(this,arguments)},setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var b=0,c=this.map.controls.length;b<c;b++){var d=this.map.controls[b];if(d.CLASS_NAME==this.argParserClass.CLASS_NAME){d.displayProjection!=
2399 this.displayProjection&&(this.displayProjection=d.displayProjection);break}}b==this.map.controls.length&&this.map.addControl(new this.argParserClass({displayProjection:this.displayProjection}))},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.element||this.anchor||(this.element=document.createElement("a"),this.element.innerHTML=OpenLayers.i18n("Permalink"),this.element.href="",this.div.appendChild(this.element));this.map.events.on({moveend:this.updateLink,changelayer:this.updateLink,
2400 changebaselayer:this.updateLink,scope:this});this.updateLink();return this.div},updateLink:function(){var a=this.anchor?"#":"?",b=this.base,c=null;-1!=b.indexOf("#")&&!1==this.anchor&&(c=b.substring(b.indexOf("#"),b.length));-1!=b.indexOf(a)&&(b=b.substring(0,b.indexOf(a)));b=b.split("#")[0]+a+OpenLayers.Util.getParameterString(this.createParams());c&&(b+=c);this.anchor&&!this.element?window.location.href=b:this.element.href=b},createParams:function(a,b,c){a=a||this.map.getCenter();var d=OpenLayers.Util.getParameters(this.base);
2401 if(a)for(d.zoom=b||this.map.getZoom(),b=a.lat,a=a.lon,this.displayProjection&&(b=OpenLayers.Projection.transform({x:a,y:b},this.map.getProjectionObject(),this.displayProjection),a=b.x,b=b.y),d.lat=Math.round(1E5*b)/1E5,d.lon=Math.round(1E5*a)/1E5,c=c||this.map.layers,d.layers="",a=0,b=c.length;a<b;a++){var e=c[a];d.layers=e.isBaseLayer?d.layers+(e==this.map.baseLayer?"B":"0"):d.layers+(e.getVisibility()?"T":"F")}return d},CLASS_NAME:"OpenLayers.Control.Permalink"});OpenLayers.Layer.TMS=OpenLayers.Class(OpenLayers.Layer.Grid,{serviceVersion:"1.0.0",layername:null,type:null,isBaseLayer:!0,tileOrigin:null,serverResolutions:null,zoomOffset:0,initialize:function(a,b,c){var d=[];d.push(a,b,{},c);OpenLayers.Layer.Grid.prototype.initialize.apply(this,d)},clone:function(a){null==a&&(a=new OpenLayers.Layer.TMS(this.name,this.url,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){a=this.adjustBounds(a);var b=this.getServerResolution(),
2402 c=Math.round((a.left-this.tileOrigin.lon)/(b*this.tileSize.w));a=Math.round((a.bottom-this.tileOrigin.lat)/(b*this.tileSize.h));b=this.getServerZoom();c=this.serviceVersion+"/"+this.layername+"/"+b+"/"+c+"/"+a+"."+this.type;a=this.url;OpenLayers.Util.isArray(a)&&(a=this.selectUrl(c,a));return a+c},setMap:function(a){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.tileOrigin||(this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.bottom))},CLASS_NAME:"OpenLayers.Layer.TMS"});OpenLayers.Format.WCSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.0",CLASS_NAME:"OpenLayers.Format.WCSCapabilities"});OpenLayers.Format.WCSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:/^\s*|\s*$/g,splitSpace:/\s+/},defaultPrefix:"wcs",read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},CLASS_NAME:"OpenLayers.Format.WCSCapabilities.v1"});OpenLayers.Format.WCSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.WCSCapabilities.v1,{namespaces:{wcs:"http://www.opengis.net/wcs",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",ows:"http://www.opengis.net/ows"},errorProperty:"service",readers:{wcs:{WCS_Capabilities:function(a,b){this.readChildNodes(a,b)},Service:function(a,b){b.service={};this.readChildNodes(a,b.service)},name:function(a,b){b.name=this.getChildValue(a)},label:function(a,b){b.label=
2403 this.getChildValue(a)},keywords:function(a,b){b.keywords=[];this.readChildNodes(a,b.keywords)},keyword:function(a,b){b.push(this.getChildValue(a))},responsibleParty:function(a,b){b.responsibleParty={};this.readChildNodes(a,b.responsibleParty)},individualName:function(a,b){b.individualName=this.getChildValue(a)},organisationName:function(a,b){b.organisationName=this.getChildValue(a)},positionName:function(a,b){b.positionName=this.getChildValue(a)},contactInfo:function(a,b){b.contactInfo={};this.readChildNodes(a,
2404 b.contactInfo)},phone:function(a,b){b.phone={};this.readChildNodes(a,b.phone)},voice:function(a,b){b.voice=this.getChildValue(a)},facsimile:function(a,b){b.facsimile=this.getChildValue(a)},address:function(a,b){b.address={};this.readChildNodes(a,b.address)},deliveryPoint:function(a,b){b.deliveryPoint=this.getChildValue(a)},city:function(a,b){b.city=this.getChildValue(a)},postalCode:function(a,b){b.postalCode=this.getChildValue(a)},country:function(a,b){b.country=this.getChildValue(a)},electronicMailAddress:function(a,
2405 b){b.electronicMailAddress=this.getChildValue(a)},fees:function(a,b){b.fees=this.getChildValue(a)},accessConstraints:function(a,b){b.accessConstraints=this.getChildValue(a)},ContentMetadata:function(a,b){b.contentMetadata=[];this.readChildNodes(a,b.contentMetadata)},CoverageOfferingBrief:function(a,b){var c={};this.readChildNodes(a,c);b.push(c)},name:function(a,b){b.name=this.getChildValue(a)},label:function(a,b){b.label=this.getChildValue(a)},lonLatEnvelope:function(a,b){var c=this.getElementsByTagNameNS(a,
2406 "http://www.opengis.net/gml","pos");if(2==c.length){var d={},e={};OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[c[0],d]);OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[c[1],e]);b.lonLatEnvelope={};b.lonLatEnvelope.srsName=a.getAttribute("srsName");b.lonLatEnvelope.min=d.points[0];b.lonLatEnvelope.max=e.points[0]}}}},CLASS_NAME:"OpenLayers.Format.WCSCapabilities.v1_0_0"});OpenLayers.Strategy.Fixed=OpenLayers.Class(OpenLayers.Strategy,{preload:!1,activate:function(){var a=OpenLayers.Strategy.prototype.activate.apply(this,arguments);if(a)if(this.layer.events.on({refresh:this.load,scope:this}),!0==this.layer.visibility||this.preload)this.load();else this.layer.events.on({visibilitychanged:this.load,scope:this});return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&this.layer.events.un({refresh:this.load,visibilitychanged:this.load,
2407 scope:this});return a},load:function(a){var b=this.layer;b.events.triggerEvent("loadstart",{filter:b.filter});b.protocol.read(OpenLayers.Util.applyDefaults({callback:this.merge,filter:b.filter,scope:this},a));b.events.un({visibilitychanged:this.load,scope:this})},merge:function(a){var b=this.layer;b.destroyFeatures();var c=a.features;if(c&&0<c.length){var d=b.projection,e=b.map.getProjectionObject();if(!e.equals(d))for(var f,g=0,h=c.length;g<h;++g)(f=c[g].geometry)&&f.transform(d,e);b.addFeatures(c)}b.events.triggerEvent("loadend",
2408 {response:a})},CLASS_NAME:"OpenLayers.Strategy.Fixed"});OpenLayers.Control.Zoom=OpenLayers.Class(OpenLayers.Control,{zoomInText:"+",zoomInId:"olZoomInLink",zoomOutText:"\u2212",zoomOutId:"olZoomOutLink",draw:function(){var a=OpenLayers.Control.prototype.draw.apply(this),b=this.getOrCreateLinks(a),c=b.zoomIn,b=b.zoomOut,d=this.map.events;b.parentNode!==a&&(d=this.events,d.attachToElement(b.parentNode));d.register("buttonclick",this,this.onZoomClick);this.zoomInLink=c;this.zoomOutLink=b;return a},getOrCreateLinks:function(a){var b=document.getElementById(this.zoomInId),
2409 c=document.getElementById(this.zoomOutId);b||(b=document.createElement("a"),b.href="#zoomIn",b.appendChild(document.createTextNode(this.zoomInText)),b.className="olControlZoomIn",a.appendChild(b));OpenLayers.Element.addClass(b,"olButton");c||(c=document.createElement("a"),c.href="#zoomOut",c.appendChild(document.createTextNode(this.zoomOutText)),c.className="olControlZoomOut",a.appendChild(c));OpenLayers.Element.addClass(c,"olButton");return{zoomIn:b,zoomOut:c}},onZoomClick:function(a){a=a.buttonElement;
2410 a===this.zoomInLink?this.map.zoomIn():a===this.zoomOutLink&&this.map.zoomOut()},destroy:function(){this.map&&this.map.events.unregister("buttonclick",this,this.onZoomClick);delete this.zoomInLink;delete this.zoomOutLink;OpenLayers.Control.prototype.destroy.apply(this)},CLASS_NAME:"OpenLayers.Control.Zoom"});OpenLayers.Layer.PointTrack=OpenLayers.Class(OpenLayers.Layer.Vector,{dataFrom:null,styleFrom:null,addNodes:function(a,b){if(2>a.length)throw Error("At least two point features have to be added to create a line from");for(var c=Array(a.length-1),d,e,f,g=0,h=a.length;g<h;g++){d=a[g];f=d.geometry;if(!f)f=d.lonlat,f=new OpenLayers.Geometry.Point(f.lon,f.lat);else if("OpenLayers.Geometry.Point"!=f.CLASS_NAME)throw new TypeError("Only features with point geometries are supported.");if(0<g){d=null!=this.dataFrom?
2411 a[g+this.dataFrom].data||a[g+this.dataFrom].attributes:null;var k=null!=this.styleFrom?a[g+this.styleFrom].style:null;e=new OpenLayers.Geometry.LineString([e,f]);c[g-1]=new OpenLayers.Feature.Vector(e,d,k)}e=f}this.addFeatures(c,b)},CLASS_NAME:"OpenLayers.Layer.PointTrack"});OpenLayers.Layer.PointTrack.SOURCE_NODE=-1;OpenLayers.Layer.PointTrack.TARGET_NODE=0;OpenLayers.Layer.PointTrack.dataFrom={SOURCE_NODE:-1,TARGET_NODE:0};OpenLayers.Protocol.WFS=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Protocol.WFS.DEFAULTS);var b=OpenLayers.Protocol.WFS["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported WFS version: "+a.version;return new b(a)};
2412 OpenLayers.Protocol.WFS.fromWMSLayer=function(a,b){var c,d;c=a.params.LAYERS;c=(OpenLayers.Util.isArray(c)?c[0]:c).split(":");1<c.length&&(d=c[0]);c=c.pop();d={url:a.url,featureType:c,featurePrefix:d,srsName:a.projection&&a.projection.getCode()||a.map&&a.map.getProjectionObject().getCode(),version:"1.1.0"};return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(b,d))};OpenLayers.Protocol.WFS.DEFAULTS={version:"1.0.0"};OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:!1,markers:null,drawn:!1,initialize:function(a,b){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.markers=[]},destroy:function(){this.clearMarkers();this.markers=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments)},setOpacity:function(a){if(a!=this.opacity){this.opacity=a;a=0;for(var b=this.markers.length;a<b;a++)this.markers[a].setOpacity(this.opacity)}},moveTo:function(a,b,c){OpenLayers.Layer.prototype.moveTo.apply(this,
2413 arguments);if(b||!this.drawn){for(var d=0,e=this.markers.length;d<e;d++)this.drawMarker(this.markers[d]);this.drawn=!0}},addMarker:function(a){this.markers.push(a);1>this.opacity&&a.setOpacity(this.opacity);this.map&&this.map.getExtent()&&(a.map=this.map,this.drawMarker(a))},removeMarker:function(a){this.markers&&this.markers.length&&(OpenLayers.Util.removeItem(this.markers,a),a.erase())},clearMarkers:function(){if(null!=this.markers)for(;0<this.markers.length;)this.removeMarker(this.markers[0])},
2414 drawMarker:function(a){var b=this.map.getLayerPxFromLonLat(a.lonlat);null==b?a.display(!1):a.isDrawn()?a.icon&&a.icon.moveTo(b):(a=a.draw(b),this.div.appendChild(a))},getDataExtent:function(){var a=null;if(this.markers&&0<this.markers.length)for(var a=new OpenLayers.Bounds,b=0,c=this.markers.length;b<c;b++)a.extend(this.markers[b].lonlat);return a},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Control.Pan=OpenLayers.Class(OpenLayers.Control.Button,{slideFactor:50,slideRatio:null,direction:null,initialize:function(a,b){this.direction=a;this.CLASS_NAME+=this.direction;OpenLayers.Control.prototype.initialize.apply(this,[b])},trigger:function(){if(this.map){var a=OpenLayers.Function.bind(function(a){return this.slideRatio?this.map.getSize()[a]*this.slideRatio:this.slideFactor},this);switch(this.direction){case OpenLayers.Control.Pan.NORTH:this.map.pan(0,-a("h"));break;case OpenLayers.Control.Pan.SOUTH:this.map.pan(0,
2415 a("h"));break;case OpenLayers.Control.Pan.WEST:this.map.pan(-a("w"),0);break;case OpenLayers.Control.Pan.EAST:this.map.pan(a("w"),0)}}},CLASS_NAME:"OpenLayers.Control.Pan"});OpenLayers.Control.Pan.NORTH="North";OpenLayers.Control.Pan.SOUTH="South";OpenLayers.Control.Pan.EAST="East";OpenLayers.Control.Pan.WEST="West";OpenLayers.Format.CSWGetDomain=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Format.CSWGetDomain.DEFAULTS);var b=OpenLayers.Format.CSWGetDomain["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported CSWGetDomain version: "+a.version;return new b(a)};OpenLayers.Format.CSWGetDomain.DEFAULTS={version:"2.0.2"};OpenLayers.Format.CSWGetDomain.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",csw:"http://www.opengis.net/cat/csw/2.0.2"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",PropertyName:null,ParameterName:null,read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==
2416 a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},readers:{csw:{GetDomainResponse:function(a,b){this.readChildNodes(a,b)},DomainValues:function(a,b){OpenLayers.Util.isArray(b.DomainValues)||(b.DomainValues=[]);for(var c=a.attributes,d={},e=0,f=c.length;e<f;++e)d[c[e].name]=c[e].nodeValue;this.readChildNodes(a,d);b.DomainValues.push(d)},PropertyName:function(a,b){b.PropertyName=this.getChildValue(a)},ParameterName:function(a,b){b.ParameterName=this.getChildValue(a)},ListOfValues:function(a,
2417 b){OpenLayers.Util.isArray(b.ListOfValues)||(b.ListOfValues=[]);this.readChildNodes(a,b.ListOfValues)},Value:function(a,b){for(var c=a.attributes,d={},e=0,f=c.length;e<f;++e)d[c[e].name]=c[e].nodeValue;d.value=this.getChildValue(a);b.push({Value:d})},ConceptualScheme:function(a,b){b.ConceptualScheme={};this.readChildNodes(a,b.ConceptualScheme)},Name:function(a,b){b.Name=this.getChildValue(a)},Document:function(a,b){b.Document=this.getChildValue(a)},Authority:function(a,b){b.Authority=this.getChildValue(a)},
2418 RangeOfValues:function(a,b){b.RangeOfValues={};this.readChildNodes(a,b.RangeOfValues)},MinValue:function(a,b){for(var c=a.attributes,d={},e=0,f=c.length;e<f;++e)d[c[e].name]=c[e].nodeValue;d.value=this.getChildValue(a);b.MinValue=d},MaxValue:function(a,b){for(var c=a.attributes,d={},e=0,f=c.length;e<f;++e)d[c[e].name]=c[e].nodeValue;d.value=this.getChildValue(a);b.MaxValue=d}}},write:function(a){a=this.writeNode("csw:GetDomain",a);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},writers:{csw:{GetDomain:function(a){var b=
2419 this.createElementNSPlus("csw:GetDomain",{attributes:{service:"CSW",version:this.version}});a.PropertyName||this.PropertyName?this.writeNode("csw:PropertyName",a.PropertyName||this.PropertyName,b):(a.ParameterName||this.ParameterName)&&this.writeNode("csw:ParameterName",a.ParameterName||this.ParameterName,b);this.readChildNodes(b,a);return b},PropertyName:function(a){return this.createElementNSPlus("csw:PropertyName",{value:a})},ParameterName:function(a){return this.createElementNSPlus("csw:ParameterName",
2420 {value:a})}}},CLASS_NAME:"OpenLayers.Format.CSWGetDomain.v2_0_2"});OpenLayers.Format.ArcXML.Features=OpenLayers.Class(OpenLayers.Format.XML,{read:function(a){return(new OpenLayers.Format.ArcXML).read(a).features.feature}});OpenLayers.Control.Snapping=OpenLayers.Class(OpenLayers.Control,{DEFAULTS:{tolerance:10,node:!0,edge:!0,vertex:!0},greedy:!0,precedence:["node","vertex","edge"],resolution:null,geoToleranceCache:null,layer:null,feature:null,point:null,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,[a]);this.options=a||{};this.options.layer&&this.setLayer(this.options.layer);a=OpenLayers.Util.extend({},this.options.defaults);this.defaults=OpenLayers.Util.applyDefaults(a,this.DEFAULTS);this.setTargets(this.options.targets);
2421 0===this.targets.length&&this.layer&&this.addTargetLayer(this.layer);this.geoToleranceCache={}},setLayer:function(a){this.active?(this.deactivate(),this.layer=a,this.activate()):this.layer=a},setTargets:function(a){this.targets=[];if(a&&a.length)for(var b,c=0,d=a.length;c<d;++c)b=a[c],b instanceof OpenLayers.Layer.Vector?this.addTargetLayer(b):this.addTarget(b)},addTargetLayer:function(a){this.addTarget({layer:a})},addTarget:function(a){a=OpenLayers.Util.applyDefaults(a,this.defaults);a.nodeTolerance=
2422 a.nodeTolerance||a.tolerance;a.vertexTolerance=a.vertexTolerance||a.tolerance;a.edgeTolerance=a.edgeTolerance||a.tolerance;this.targets.push(a)},removeTargetLayer:function(a){for(var b,c=this.targets.length-1;0<=c;--c)b=this.targets[c],b.layer===a&&this.removeTarget(b)},removeTarget:function(a){return OpenLayers.Util.removeItem(this.targets,a)},activate:function(){var a=OpenLayers.Control.prototype.activate.call(this);if(a&&this.layer&&this.layer.events)this.layer.events.on({sketchstarted:this.onSketchModified,
2423 sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});return a},deactivate:function(){var a=OpenLayers.Control.prototype.deactivate.call(this);a&&this.layer&&this.layer.events&&this.layer.events.un({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});this.point=this.feature=null;return a},onSketchModified:function(a){this.feature=a.feature;this.considerSnapping(a.vertex,a.vertex)},onVertexModified:function(a){this.feature=
2424 a.feature;var b=this.layer.map.getLonLatFromViewPortPx(a.pixel);this.considerSnapping(a.vertex,new OpenLayers.Geometry.Point(b.lon,b.lat))},considerSnapping:function(a,b){for(var c={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY,x:null,y:null},d=!1,e,f,g=0,h=this.targets.length;g<h;++g)if(f=this.targets[g],e=this.testTarget(f,b))if(this.greedy){c=e;c.target=f;d=!0;break}else if(e.rank<c.rank||e.rank===c.rank&&e.dist<c.dist)c=e,c.target=f,d=!0;d&&(!1!==this.events.triggerEvent("beforesnap",
2425 {point:a,x:c.x,y:c.y,distance:c.dist,layer:c.target.layer,snapType:this.precedence[c.rank]})?(a.x=c.x,a.y=c.y,this.point=a,this.events.triggerEvent("snap",{point:a,snapType:this.precedence[c.rank],layer:c.target.layer,distance:c.dist})):d=!1);this.point&&!d&&(a.x=b.x,a.y=b.y,this.point=null,this.events.triggerEvent("unsnap",{point:a}))},testTarget:function(a,b){var c=this.layer.map.getResolution();if("minResolution"in a&&c<a.minResolution||"maxResolution"in a&&c>=a.maxResolution)return null;for(var c=
2426 {node:this.getGeoTolerance(a.nodeTolerance,c),vertex:this.getGeoTolerance(a.vertexTolerance,c),edge:this.getGeoTolerance(a.edgeTolerance,c)},d=Math.max(c.node,c.vertex,c.edge),e={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY},f=!1,g=a.layer.features,h,k,l,m,n,p,q=this.precedence.length,r=new OpenLayers.LonLat(b.x,b.y),s=0,t=g.length;s<t;++s)if(h=g[s],h!==this.feature&&(!h._sketch&&h.state!==OpenLayers.State.DELETE&&(!a.filter||a.filter.evaluate(h)))&&h.atPoint(r,d,d))for(var u=0,v=Math.min(e.rank+
2427 1,q);u<v;++u)if(k=this.precedence[u],a[k])if("edge"===k){if(l=h.geometry.distanceTo(b,{details:!0}),n=l.distance,n<=c[k]&&n<e.dist){e={rank:u,dist:n,x:l.x0,y:l.y0};f=!0;break}}else{l=h.geometry.getVertices("node"===k);p=!1;for(var w=0,x=l.length;w<x;++w)m=l[w],n=m.distanceTo(b),n<=c[k]&&(u<e.rank||u===e.rank&&n<e.dist)&&(e={rank:u,dist:n,x:m.x,y:m.y},p=f=!0);if(p)break}return f?e:null},getGeoTolerance:function(a,b){b!==this.resolution&&(this.resolution=b,this.geoToleranceCache={});var c=this.geoToleranceCache[a];
2428 void 0===c&&(c=a*b,this.geoToleranceCache[a]=c);return c},destroy:function(){this.active&&this.deactivate();delete this.layer;delete this.targets;OpenLayers.Control.prototype.destroy.call(this)},CLASS_NAME:"OpenLayers.Control.Snapping"});OpenLayers.Format.OWSCommon.v1_1_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows/1.1",xlink:"http://www.w3.org/1999/xlink"},readers:{ows:OpenLayers.Util.applyDefaults({ExceptionReport:function(a,b){b.exceptionReport={version:a.getAttribute("version"),language:a.getAttribute("xml:lang"),exceptions:[]};this.readChildNodes(a,b.exceptionReport)},AllowedValues:function(a,b){b.allowedValues={};this.readChildNodes(a,b.allowedValues)},AnyValue:function(a,b){b.anyValue=
2429 !0},DataType:function(a,b){b.dataType=this.getChildValue(a)},Range:function(a,b){b.range={};this.readChildNodes(a,b.range)},MinimumValue:function(a,b){b.minValue=this.getChildValue(a)},MaximumValue:function(a,b){b.maxValue=this.getChildValue(a)},Identifier:function(a,b){b.identifier=this.getChildValue(a)},SupportedCRS:function(a,b){b.supportedCRS=this.getChildValue(a)}},OpenLayers.Format.OWSCommon.v1.prototype.readers.ows)},writers:{ows:OpenLayers.Util.applyDefaults({Range:function(a){var b=this.createElementNSPlus("ows:Range",
2430 {attributes:{"ows:rangeClosure":a.closure}});this.writeNode("ows:MinimumValue",a.minValue,b);this.writeNode("ows:MaximumValue",a.maxValue,b);return b},MinimumValue:function(a){return this.createElementNSPlus("ows:MinimumValue",{value:a})},MaximumValue:function(a){return this.createElementNSPlus("ows:MaximumValue",{value:a})},Value:function(a){return this.createElementNSPlus("ows:Value",{value:a})}},OpenLayers.Format.OWSCommon.v1.prototype.writers.ows)},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});OpenLayers.Format.WCSGetCoverage=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows/1.1",wcs:"http://www.opengis.net/wcs/1.1",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},VERSION:"1.1.2",schemaLocation:"http://www.opengis.net/wcs/1.1 http://schemas.opengis.net/wcs/1.1/wcsGetCoverage.xsd",write:function(a){a=this.writeNode("wcs:GetCoverage",
2431 a);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},writers:{wcs:{GetCoverage:function(a){var b=this.createElementNSPlus("wcs:GetCoverage",{attributes:{version:a.version||this.VERSION,service:"WCS"}});this.writeNode("ows:Identifier",a.identifier,b);this.writeNode("wcs:DomainSubset",a.domainSubset,b);this.writeNode("wcs:Output",a.output,b);return b},DomainSubset:function(a){var b=this.createElementNSPlus("wcs:DomainSubset",
2432 {});this.writeNode("ows:BoundingBox",a.boundingBox,b);a.temporalSubset&&this.writeNode("wcs:TemporalSubset",a.temporalSubset,b);return b},TemporalSubset:function(a){for(var b=this.createElementNSPlus("wcs:TemporalSubset",{}),c=0,d=a.timePeriods.length;c<d;++c)this.writeNode("wcs:TimePeriod",a.timePeriods[c],b);return b},TimePeriod:function(a){var b=this.createElementNSPlus("wcs:TimePeriod",{});this.writeNode("wcs:BeginPosition",a.begin,b);this.writeNode("wcs:EndPosition",a.end,b);a.resolution&&this.writeNode("wcs:TimeResolution",
2433 a.resolution,b);return b},BeginPosition:function(a){return this.createElementNSPlus("wcs:BeginPosition",{value:a})},EndPosition:function(a){return this.createElementNSPlus("wcs:EndPosition",{value:a})},TimeResolution:function(a){return this.createElementNSPlus("wcs:TimeResolution",{value:a})},Output:function(a){var b=this.createElementNSPlus("wcs:Output",{attributes:{format:a.format,store:a.store}});a.gridCRS&&this.writeNode("wcs:GridCRS",a.gridCRS,b);return b},GridCRS:function(a){var b=this.createElementNSPlus("wcs:GridCRS",
2434 {});this.writeNode("wcs:GridBaseCRS",a.baseCRS,b);a.type&&this.writeNode("wcs:GridType",a.type,b);a.origin&&this.writeNode("wcs:GridOrigin",a.origin,b);this.writeNode("wcs:GridOffsets",a.offsets,b);a.CS&&this.writeNode("wcs:GridCS",a.CS,b);return b},GridBaseCRS:function(a){return this.createElementNSPlus("wcs:GridBaseCRS",{value:a})},GridOrigin:function(a){return this.createElementNSPlus("wcs:GridOrigin",{value:a})},GridType:function(a){return this.createElementNSPlus("wcs:GridType",{value:a})},GridOffsets:function(a){return this.createElementNSPlus("wcs:GridOffsets",
2435 {value:a})},GridCS:function(a){return this.createElementNSPlus("wcs:GridCS",{value:a})}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows},CLASS_NAME:"OpenLayers.Format.WCSGetCoverage"});OpenLayers.Format.KML=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{kml:"http://www.opengis.net/kml/2.2",gx:"http://www.google.com/kml/ext/2.2"},kmlns:"http://earth.google.com/kml/2.0",placemarksDesc:"No description available",foldersName:"OpenLayers export",foldersDesc:"Exported on "+new Date,extractAttributes:!0,kvpAttributes:!1,extractStyles:!1,extractTracks:!1,trackAttributes:null,internalns:null,features:null,styles:null,styleBaseUrl:"",fetched:null,maxDepth:0,initialize:function(a){this.regExes=
2436 {trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g,kmlColor:/(\w{2})(\w{2})(\w{2})(\w{2})/,kmlIconPalette:/root:\/\/icons\/palette-(\d+)(\.\w+)/,straightBracket:/\$\[(.*?)\]/g};this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){this.features=[];this.styles={};this.fetched={};return this.parseData(a,{depth:0,styleBaseUrl:this.styleBaseUrl})},parseData:function(a,b){"string"==typeof a&&
2437 (a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));for(var c=["Link","NetworkLink","Style","StyleMap","Placemark"],d=0,e=c.length;d<e;++d){var f=c[d],g=this.getElementsByTagNameNS(a,"*",f);if(0!=g.length)switch(f.toLowerCase()){case "link":case "networklink":this.parseLinks(g,b);break;case "style":this.extractStyles&&this.parseStyles(g,b);break;case "stylemap":this.extractStyles&&this.parseStyleMaps(g,b);break;case "placemark":this.parseFeatures(g,b)}}return this.features},parseLinks:function(a,
2438 b){if(b.depth>=this.maxDepth)return!1;var c=OpenLayers.Util.extend({},b);c.depth++;for(var d=0,e=a.length;d<e;d++){var f=this.parseProperty(a[d],"*","href");f&&!this.fetched[f]&&(this.fetched[f]=!0,(f=this.fetchLink(f))&&this.parseData(f,c))}},fetchLink:function(a){if(a=OpenLayers.Request.GET({url:a,async:!1}))return a.responseText},parseStyles:function(a,b){for(var c=0,d=a.length;c<d;c++){var e=this.parseStyle(a[c]);e&&(this.styles[(b.styleBaseUrl||"")+"#"+e.id]=e)}},parseKmlColor:function(a){var b=
2439 null;a&&(a=a.match(this.regExes.kmlColor))&&(b={color:"#"+a[4]+a[3]+a[2],opacity:parseInt(a[1],16)/255});return b},parseStyle:function(a){for(var b={},c=["LineStyle","PolyStyle","IconStyle","BalloonStyle","LabelStyle"],d,e,f=0,g=c.length;f<g;++f)if(d=c[f],e=this.getElementsByTagNameNS(a,"*",d)[0])switch(d.toLowerCase()){case "linestyle":d=this.parseProperty(e,"*","color");if(d=this.parseKmlColor(d))b.strokeColor=d.color,b.strokeOpacity=d.opacity;(d=this.parseProperty(e,"*","width"))&&(b.strokeWidth=
2440 d);break;case "polystyle":d=this.parseProperty(e,"*","color");if(d=this.parseKmlColor(d))b.fillOpacity=d.opacity,b.fillColor=d.color;"0"==this.parseProperty(e,"*","fill")&&(b.fillColor="none");"0"==this.parseProperty(e,"*","outline")&&(b.strokeWidth="0");break;case "iconstyle":var h=parseFloat(this.parseProperty(e,"*","scale")||1);d=32*h;var k=32*h,l=this.getElementsByTagNameNS(e,"*","Icon")[0];if(l){var m=this.parseProperty(l,"*","href");if(m){var n=this.parseProperty(l,"*","w"),p=this.parseProperty(l,
2441 "*","h");!OpenLayers.String.startsWith(m,"http://maps.google.com/mapfiles/kml")||(n||p)||(p=n=64,h/=2);n=n||p;p=p||n;n&&(d=parseInt(n)*h);p&&(k=parseInt(p)*h);if(p=m.match(this.regExes.kmlIconPalette))n=p[1],p=p[2],m=this.parseProperty(l,"*","x"),l=this.parseProperty(l,"*","y"),m="http://maps.google.com/mapfiles/kml/pal"+n+"/icon"+(8*(l?7-l/32:7)+(m?m/32:0))+p;b.graphicOpacity=1;b.externalGraphic=m}}if(e=this.getElementsByTagNameNS(e,"*","hotSpot")[0])m=parseFloat(e.getAttribute("x")),l=parseFloat(e.getAttribute("y")),
2442 n=e.getAttribute("xunits"),"pixels"==n?b.graphicXOffset=-m*h:"insetPixels"==n?b.graphicXOffset=-d+m*h:"fraction"==n&&(b.graphicXOffset=-d*m),e=e.getAttribute("yunits"),"pixels"==e?b.graphicYOffset=-k+l*h+1:"insetPixels"==e?b.graphicYOffset=-(l*h)+1:"fraction"==e&&(b.graphicYOffset=-k*(1-l)+1);b.graphicWidth=d;b.graphicHeight=k;break;case "balloonstyle":(e=OpenLayers.Util.getXmlNodeValue(e))&&(b.balloonStyle=e.replace(this.regExes.straightBracket,"${$1}"));break;case "labelstyle":if(d=this.parseProperty(e,
2443 "*","color"),d=this.parseKmlColor(d))b.fontColor=d.color,b.fontOpacity=d.opacity}!b.strokeColor&&b.fillColor&&(b.strokeColor=b.fillColor);(a=a.getAttribute("id"))&&b&&(b.id=a);return b},parseStyleMaps:function(a,b){for(var c=0,d=a.length;c<d;c++)for(var e=a[c],f=this.getElementsByTagNameNS(e,"*","Pair"),e=e.getAttribute("id"),g=0,h=f.length;g<h;g++){var k=f[g],l=this.parseProperty(k,"*","key");(k=this.parseProperty(k,"*","styleUrl"))&&"normal"==l&&(this.styles[(b.styleBaseUrl||"")+"#"+e]=this.styles[(b.styleBaseUrl||
2444 "")+k])}},parseFeatures:function(a,b){for(var c=[],d=0,e=a.length;d<e;d++){var f=a[d],g=this.parseFeature.apply(this,[f]);if(g){this.extractStyles&&(g.attributes&&g.attributes.styleUrl)&&(g.style=this.getStyle(g.attributes.styleUrl,b));if(this.extractStyles){var h=this.getElementsByTagNameNS(f,"*","Style")[0];h&&(h=this.parseStyle(h))&&(g.style=OpenLayers.Util.extend(g.style,h))}this.extractTracks?(f=this.getElementsByTagNameNS(f,this.namespaces.gx,"Track"))&&0<f.length&&(g={features:[],feature:g},
2445 this.readNode(f[0],g),0<g.features.length&&c.push.apply(c,g.features)):c.push(g)}else throw"Bad Placemark: "+d;}this.features=this.features.concat(c)},readers:{kml:{when:function(a,b){b.whens.push(OpenLayers.Date.parse(this.getChildValue(a)))},_trackPointAttribute:function(a,b){var c=a.nodeName.split(":").pop();b.attributes[c].push(this.getChildValue(a))}},gx:{Track:function(a,b){var c={whens:[],points:[],angles:[]};if(this.trackAttributes){var d;c.attributes={};for(var e=0,f=this.trackAttributes.length;e<
2446 f;++e)d=this.trackAttributes[e],c.attributes[d]=[],d in this.readers.kml||(this.readers.kml[d]=this.readers.kml._trackPointAttribute)}this.readChildNodes(a,c);if(c.whens.length!==c.points.length)throw Error("gx:Track with unequal number of when ("+c.whens.length+") and gx:coord ("+c.points.length+") elements.");var g=0<c.angles.length;if(g&&c.whens.length!==c.angles.length)throw Error("gx:Track with unequal number of when ("+c.whens.length+") and gx:angles ("+c.angles.length+") elements.");for(var h,
2447 e=0,f=c.whens.length;e<f;++e){h=b.feature.clone();h.fid=b.feature.fid||b.feature.id;d=c.points[e];h.geometry=d;"z"in d&&(h.attributes.altitude=d.z);this.internalProjection&&this.externalProjection&&h.geometry.transform(this.externalProjection,this.internalProjection);if(this.trackAttributes)for(var k=0,l=this.trackAttributes.length;k<l;++k)d=this.trackAttributes[k],h.attributes[d]=c.attributes[d][e];h.attributes.when=c.whens[e];h.attributes.trackId=b.feature.id;g&&(d=c.angles[e],h.attributes.heading=
2448 parseFloat(d[0]),h.attributes.tilt=parseFloat(d[1]),h.attributes.roll=parseFloat(d[2]));b.features.push(h)}},coord:function(a,b){var c=this.getChildValue(a).replace(this.regExes.trimSpace,"").split(/\s+/),d=new OpenLayers.Geometry.Point(c[0],c[1]);2<c.length&&(d.z=parseFloat(c[2]));b.points.push(d)},angles:function(a,b){var c=this.getChildValue(a).replace(this.regExes.trimSpace,"").split(/\s+/);b.angles.push(c)}}},parseFeature:function(a){for(var b=["MultiGeometry","Polygon","LineString","Point"],
2449 c,d,e,f=0,g=b.length;f<g;++f)if(c=b[f],this.internalns=a.namespaceURI?a.namespaceURI:this.kmlns,d=this.getElementsByTagNameNS(a,this.internalns,c),0<d.length){if(b=this.parseGeometry[c.toLowerCase()])e=b.apply(this,[d[0]]),this.internalProjection&&this.externalProjection&&e.transform(this.externalProjection,this.internalProjection);else throw new TypeError("Unsupported geometry type: "+c);break}var h;this.extractAttributes&&(h=this.parseAttributes(a));c=new OpenLayers.Feature.Vector(e,h);a=a.getAttribute("id")||
2450 a.getAttribute("name");null!=a&&(c.fid=a);return c},getStyle:function(a,b){var c=OpenLayers.Util.removeTail(a),d=OpenLayers.Util.extend({},b);d.depth++;d.styleBaseUrl=c;!this.styles[a]&&!OpenLayers.String.startsWith(a,"#")&&d.depth<=this.maxDepth&&!this.fetched[c]&&(c=this.fetchLink(c))&&this.parseData(c,d);return OpenLayers.Util.extend({},this.styles[a])},parseGeometry:{point:function(a){var b=this.getElementsByTagNameNS(a,this.internalns,"coordinates");a=[];if(0<b.length){var c=b[0].firstChild.nodeValue,
2451 c=c.replace(this.regExes.removeSpace,"");a=c.split(",")}b=null;if(1<a.length)2==a.length&&(a[2]=null),b=new OpenLayers.Geometry.Point(a[0],a[1],a[2]);else throw"Bad coordinate string: "+c;return b},linestring:function(a,b){var c=this.getElementsByTagNameNS(a,this.internalns,"coordinates"),d=null;if(0<c.length){for(var c=this.getChildValue(c[0]),c=c.replace(this.regExes.trimSpace,""),c=c.replace(this.regExes.trimComma,","),d=c.split(this.regExes.splitSpace),e=d.length,f=Array(e),g,h,k=0;k<e;++k)if(g=
2452 d[k].split(","),h=g.length,1<h)2==g.length&&(g[2]=null),f[k]=new OpenLayers.Geometry.Point(g[0],g[1],g[2]);else throw"Bad LineString point coordinates: "+d[k];if(e)d=b?new OpenLayers.Geometry.LinearRing(f):new OpenLayers.Geometry.LineString(f);else throw"Bad LineString coordinates: "+c;}return d},polygon:function(a){a=this.getElementsByTagNameNS(a,this.internalns,"LinearRing");var b=a.length,c=Array(b);if(0<b)for(var d=0,e=a.length;d<e;++d)if(b=this.parseGeometry.linestring.apply(this,[a[d],!0]))c[d]=
2453 b;else throw"Bad LinearRing geometry: "+d;return new OpenLayers.Geometry.Polygon(c)},multigeometry:function(a){for(var b,c=[],d=a.childNodes,e=0,f=d.length;e<f;++e)a=d[e],1==a.nodeType&&(b=a.prefix?a.nodeName.split(":")[1]:a.nodeName,(b=this.parseGeometry[b.toLowerCase()])&&c.push(b.apply(this,[a])));return new OpenLayers.Geometry.Collection(c)}},parseAttributes:function(a){var b={},c=a.getElementsByTagName("ExtendedData");c.length&&(b=this.parseExtendedData(c[0]));var d,e,f;a=a.childNodes;for(var c=
2454 0,g=a.length;c<g;++c)if(d=a[c],1==d.nodeType&&(e=d.childNodes,1<=e.length&&3>=e.length)){switch(e.length){case 1:f=e[0];break;case 2:f=e[0];e=e[1];f=3==f.nodeType||4==f.nodeType?f:e;break;default:f=e[1]}if(3==f.nodeType||4==f.nodeType)if(d=d.prefix?d.nodeName.split(":")[1]:d.nodeName,f=OpenLayers.Util.getXmlNodeValue(f))f=f.replace(this.regExes.trimSpace,""),b[d]=f}return b},parseExtendedData:function(a){var b={},c,d,e,f,g=a.getElementsByTagName("Data");c=0;for(d=g.length;c<d;c++){e=g[c];f=e.getAttribute("name");
2455 var h={},k=e.getElementsByTagName("value");k.length&&(h.value=this.getChildValue(k[0]));this.kvpAttributes?b[f]=h.value:(e=e.getElementsByTagName("displayName"),e.length&&(h.displayName=this.getChildValue(e[0])),b[f]=h)}a=a.getElementsByTagName("SimpleData");c=0;for(d=a.length;c<d;c++)h={},e=a[c],f=e.getAttribute("name"),h.value=this.getChildValue(e),this.kvpAttributes?b[f]=h.value:(h.displayName=f,b[f]=h);return b},parseProperty:function(a,b,c){var d;a=this.getElementsByTagNameNS(a,b,c);try{d=OpenLayers.Util.getXmlNodeValue(a[0])}catch(e){d=
2456 null}return d},write:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=this.createElementNS(this.kmlns,"kml"),c=this.createFolderXML(),d=0,e=a.length;d<e;++d)c.appendChild(this.createPlacemarkXML(a[d]));b.appendChild(c);return OpenLayers.Format.XML.prototype.write.apply(this,[b])},createFolderXML:function(){var a=this.createElementNS(this.kmlns,"Folder");if(this.foldersName){var b=this.createElementNS(this.kmlns,"name"),c=this.createTextNode(this.foldersName);b.appendChild(c);a.appendChild(b)}this.foldersDesc&&
2457 (b=this.createElementNS(this.kmlns,"description"),c=this.createTextNode(this.foldersDesc),b.appendChild(c),a.appendChild(b));return a},createPlacemarkXML:function(a){var b=this.createElementNS(this.kmlns,"name"),c=a.style&&a.style.label?a.style.label:a.id;b.appendChild(this.createTextNode(a.attributes.name||c));var d=this.createElementNS(this.kmlns,"description");d.appendChild(this.createTextNode(a.attributes.description||this.placemarksDesc));c=this.createElementNS(this.kmlns,"Placemark");null!=
2458 a.fid&&c.setAttribute("id",a.fid);c.appendChild(b);c.appendChild(d);b=this.buildGeometryNode(a.geometry);c.appendChild(b);a.attributes&&(a=this.buildExtendedData(a.attributes))&&c.appendChild(a);return c},buildGeometryNode:function(a){var b=a.CLASS_NAME,b=b.substring(b.lastIndexOf(".")+1),b=this.buildGeometry[b.toLowerCase()],c=null;b&&(c=b.apply(this,[a]));return c},buildGeometry:{point:function(a){var b=this.createElementNS(this.kmlns,"Point");b.appendChild(this.buildCoordinatesNode(a));return b},
2459 multipoint:function(a){return this.buildGeometry.collection.apply(this,[a])},linestring:function(a){var b=this.createElementNS(this.kmlns,"LineString");b.appendChild(this.buildCoordinatesNode(a));return b},multilinestring:function(a){return this.buildGeometry.collection.apply(this,[a])},linearring:function(a){var b=this.createElementNS(this.kmlns,"LinearRing");b.appendChild(this.buildCoordinatesNode(a));return b},polygon:function(a){var b=this.createElementNS(this.kmlns,"Polygon");a=a.components;
2460 for(var c,d,e=0,f=a.length;e<f;++e)c=0==e?"outerBoundaryIs":"innerBoundaryIs",c=this.createElementNS(this.kmlns,c),d=this.buildGeometry.linearring.apply(this,[a[e]]),c.appendChild(d),b.appendChild(c);return b},multipolygon:function(a){return this.buildGeometry.collection.apply(this,[a])},collection:function(a){for(var b=this.createElementNS(this.kmlns,"MultiGeometry"),c,d=0,e=a.components.length;d<e;++d)(c=this.buildGeometryNode.apply(this,[a.components[d]]))&&b.appendChild(c);return b}},buildCoordinatesNode:function(a){var b=
2461 this.createElementNS(this.kmlns,"coordinates"),c;if(c=a.components){for(var d=c.length,e=Array(d),f=0;f<d;++f)a=c[f],e[f]=this.buildCoordinates(a);c=e.join(" ")}else c=this.buildCoordinates(a);c=this.createTextNode(c);b.appendChild(c);return b},buildCoordinates:function(a){this.internalProjection&&this.externalProjection&&(a=a.clone(),a.transform(this.internalProjection,this.externalProjection));return a.x+","+a.y},buildExtendedData:function(a){var b=this.createElementNS(this.kmlns,"ExtendedData"),
2462 c;for(c in a)if(a[c]&&"name"!=c&&"description"!=c&&"styleUrl"!=c){var d=this.createElementNS(this.kmlns,"Data");d.setAttribute("name",c);var e=this.createElementNS(this.kmlns,"value");if("object"==typeof a[c]){if(a[c].value&&e.appendChild(this.createTextNode(a[c].value)),a[c].displayName){var f=this.createElementNS(this.kmlns,"displayName");f.appendChild(this.getXMLDoc().createCDATASection(a[c].displayName));d.appendChild(f)}}else e.appendChild(this.createTextNode(a[c]));d.appendChild(e);b.appendChild(d)}return this.isSimpleContent(b)?
2463 null:b},CLASS_NAME:"OpenLayers.Format.KML"});OpenLayers.Format.WMSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.1",profile:null,CLASS_NAME:"OpenLayers.Format.WMSCapabilities"});OpenLayers.Format.WMSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{wms:"http://www.opengis.net/wms",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"wms",read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=a;a&&9==a.nodeType&&(a=a.documentElement);var c={};this.readNode(a,c);void 0===c.service&&(a=new OpenLayers.Format.OGCExceptionReport,c.error=a.read(b));return c},readers:{wms:{Service:function(a,
2464 b){b.service={};this.readChildNodes(a,b.service)},Name:function(a,b){b.name=this.getChildValue(a)},Title:function(a,b){b.title=this.getChildValue(a)},Abstract:function(a,b){b["abstract"]=this.getChildValue(a)},BoundingBox:function(a,b){var c={};c.bbox=[parseFloat(a.getAttribute("minx")),parseFloat(a.getAttribute("miny")),parseFloat(a.getAttribute("maxx")),parseFloat(a.getAttribute("maxy"))];var d={x:parseFloat(a.getAttribute("resx")),y:parseFloat(a.getAttribute("resy"))};isNaN(d.x)&&isNaN(d.y)||(c.res=
2465 d);return c},OnlineResource:function(a,b){b.href=this.getAttributeNS(a,this.namespaces.xlink,"href")},ContactInformation:function(a,b){b.contactInformation={};this.readChildNodes(a,b.contactInformation)},ContactPersonPrimary:function(a,b){b.personPrimary={};this.readChildNodes(a,b.personPrimary)},ContactPerson:function(a,b){b.person=this.getChildValue(a)},ContactOrganization:function(a,b){b.organization=this.getChildValue(a)},ContactPosition:function(a,b){b.position=this.getChildValue(a)},ContactAddress:function(a,
2466 b){b.contactAddress={};this.readChildNodes(a,b.contactAddress)},AddressType:function(a,b){b.type=this.getChildValue(a)},Address:function(a,b){b.address=this.getChildValue(a)},City:function(a,b){b.city=this.getChildValue(a)},StateOrProvince:function(a,b){b.stateOrProvince=this.getChildValue(a)},PostCode:function(a,b){b.postcode=this.getChildValue(a)},Country:function(a,b){b.country=this.getChildValue(a)},ContactVoiceTelephone:function(a,b){b.phone=this.getChildValue(a)},ContactFacsimileTelephone:function(a,
2467 b){b.fax=this.getChildValue(a)},ContactElectronicMailAddress:function(a,b){b.email=this.getChildValue(a)},Fees:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.fees=c)},AccessConstraints:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.accessConstraints=c)},Capability:function(a,b){b.capability={nestedLayers:[],layers:[]};this.readChildNodes(a,b.capability)},Request:function(a,b){b.request={};this.readChildNodes(a,b.request)},GetCapabilities:function(a,
2468 b){b.getcapabilities={formats:[]};this.readChildNodes(a,b.getcapabilities)},Format:function(a,b){OpenLayers.Util.isArray(b.formats)?b.formats.push(this.getChildValue(a)):b.format=this.getChildValue(a)},DCPType:function(a,b){this.readChildNodes(a,b)},HTTP:function(a,b){this.readChildNodes(a,b)},Get:function(a,b){b.get={};this.readChildNodes(a,b.get);b.href||(b.href=b.get.href)},Post:function(a,b){b.post={};this.readChildNodes(a,b.post);b.href||(b.href=b.get.href)},GetMap:function(a,b){b.getmap={formats:[]};
2469 this.readChildNodes(a,b.getmap)},GetFeatureInfo:function(a,b){b.getfeatureinfo={formats:[]};this.readChildNodes(a,b.getfeatureinfo)},Exception:function(a,b){b.exception={formats:[]};this.readChildNodes(a,b.exception)},Layer:function(a,b){var c,d;b.capability?(d=b.capability,c=b):d=b;var e=a.getAttributeNode("queryable"),f=e&&e.specified?a.getAttribute("queryable"):null,g=(e=a.getAttributeNode("cascaded"))&&e.specified?a.getAttribute("cascaded"):null,e=(e=a.getAttributeNode("opaque"))&&e.specified?
2470 a.getAttribute("opaque"):null,h=a.getAttribute("noSubsets"),k=a.getAttribute("fixedWidth"),l=a.getAttribute("fixedHeight"),m=c||{},n=OpenLayers.Util.extend;c={nestedLayers:[],styles:c?[].concat(c.styles):[],srs:c?n({},m.srs):{},metadataURLs:[],bbox:c?n({},m.bbox):{},llbbox:m.llbbox,dimensions:c?n({},m.dimensions):{},authorityURLs:c?n({},m.authorityURLs):{},identifiers:{},keywords:[],queryable:f&&""!==f?"1"===f||"true"===f:m.queryable||!1,cascaded:null!==g?parseInt(g):m.cascaded||0,opaque:e?"1"===
2471 e||"true"===e:m.opaque||!1,noSubsets:null!==h?"1"===h||"true"===h:m.noSubsets||!1,fixedWidth:null!=k?parseInt(k):m.fixedWidth||0,fixedHeight:null!=l?parseInt(l):m.fixedHeight||0,minScale:m.minScale,maxScale:m.maxScale,attribution:m.attribution};b.nestedLayers.push(c);c.capability=d;this.readChildNodes(a,c);delete c.capability;c.name&&(f=c.name.split(":"),g=d.request,e=g.getfeatureinfo,0<f.length&&(c.prefix=f[0]),d.layers.push(c),void 0===c.formats&&(c.formats=g.getmap.formats),void 0===c.infoFormats&&
2472 e&&(c.infoFormats=e.formats))},Attribution:function(a,b){b.attribution={};this.readChildNodes(a,b.attribution)},LogoURL:function(a,b){b.logo={width:a.getAttribute("width"),height:a.getAttribute("height")};this.readChildNodes(a,b.logo)},Style:function(a,b){var c={};b.styles.push(c);this.readChildNodes(a,c)},LegendURL:function(a,b){var c={width:a.getAttribute("width"),height:a.getAttribute("height")};b.legend=c;this.readChildNodes(a,c)},MetadataURL:function(a,b){var c={type:a.getAttribute("type")};
2473 b.metadataURLs.push(c);this.readChildNodes(a,c)},DataURL:function(a,b){b.dataURL={};this.readChildNodes(a,b.dataURL)},FeatureListURL:function(a,b){b.featureListURL={};this.readChildNodes(a,b.featureListURL)},AuthorityURL:function(a,b){var c=a.getAttribute("name"),d={};this.readChildNodes(a,d);b.authorityURLs[c]=d.href},Identifier:function(a,b){var c=a.getAttribute("authority");b.identifiers[c]=this.getChildValue(a)},KeywordList:function(a,b){this.readChildNodes(a,b)},SRS:function(a,b){b.srs[this.getChildValue(a)]=
2474 !0}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1"});OpenLayers.Format.WMSCapabilities.v1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{wms:OpenLayers.Util.applyDefaults({WMT_MS_Capabilities:function(a,b){this.readChildNodes(a,b)},Keyword:function(a,b){b.keywords&&b.keywords.push(this.getChildValue(a))},DescribeLayer:function(a,b){b.describelayer={formats:[]};this.readChildNodes(a,b.describelayer)},GetLegendGraphic:function(a,b){b.getlegendgraphic={formats:[]};this.readChildNodes(a,b.getlegendgraphic)},GetStyles:function(a,b){b.getstyles=
2475 {formats:[]};this.readChildNodes(a,b.getstyles)},PutStyles:function(a,b){b.putstyles={formats:[]};this.readChildNodes(a,b.putstyles)},UserDefinedSymbolization:function(a,b){var c={supportSLD:1==parseInt(a.getAttribute("SupportSLD")),userLayer:1==parseInt(a.getAttribute("UserLayer")),userStyle:1==parseInt(a.getAttribute("UserStyle")),remoteWFS:1==parseInt(a.getAttribute("RemoteWFS"))};b.userSymbols=c},LatLonBoundingBox:function(a,b){b.llbbox=[parseFloat(a.getAttribute("minx")),parseFloat(a.getAttribute("miny")),
2476 parseFloat(a.getAttribute("maxx")),parseFloat(a.getAttribute("maxy"))]},BoundingBox:function(a,b){var c=OpenLayers.Format.WMSCapabilities.v1.prototype.readers.wms.BoundingBox.apply(this,[a,b]);c.srs=a.getAttribute("SRS");b.bbox[c.srs]=c},ScaleHint:function(a,b){var c=a.getAttribute("min"),d=a.getAttribute("max"),e=Math.pow(2,0.5),f=OpenLayers.INCHES_PER_UNIT.m;0!=c&&(b.maxScale=parseFloat((c/e*f*OpenLayers.DOTS_PER_INCH).toPrecision(13)));d!=Number.POSITIVE_INFINITY&&(b.minScale=parseFloat((d/e*f*
2477 OpenLayers.DOTS_PER_INCH).toPrecision(13)))},Dimension:function(a,b){var c={name:a.getAttribute("name").toLowerCase(),units:a.getAttribute("units"),unitsymbol:a.getAttribute("unitSymbol")};b.dimensions[c.name]=c},Extent:function(a,b){var c=a.getAttribute("name").toLowerCase();if(c in b.dimensions){c=b.dimensions[c];c.nearestVal="1"===a.getAttribute("nearestValue");c.multipleVal="1"===a.getAttribute("multipleValues");c.current="1"===a.getAttribute("current");c["default"]=a.getAttribute("default")||
2478 "";var d=this.getChildValue(a);c.values=d.split(",")}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers.wms)},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1"});OpenLayers.Format.WMSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.0",readers:{wms:OpenLayers.Util.applyDefaults({SRS:function(a,b){for(var c=this.getChildValue(a).split(/ +/),d=0,e=c.length;d<e;d++)b.srs[c[d]]=!0}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers.wms)},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_0"});OpenLayers.Protocol.WFS.v1=OpenLayers.Class(OpenLayers.Protocol,{version:null,srsName:"EPSG:4326",featureType:null,featureNS:null,geometryName:"the_geom",schema:null,featurePrefix:"feature",formatOptions:null,readFormat:null,readOptions:null,initialize:function(a){OpenLayers.Protocol.prototype.initialize.apply(this,[a]);a.format||(this.format=OpenLayers.Format.WFST(OpenLayers.Util.extend({version:this.version,featureType:this.featureType,featureNS:this.featureNS,featurePrefix:this.featurePrefix,geometryName:this.geometryName,
2479 srsName:this.srsName,schema:this.schema},this.formatOptions)));!a.geometryName&&1<parseFloat(this.format.version)&&this.setGeometryName(null)},destroy:function(){this.options&&!this.options.format&&this.format.destroy();this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this)},read:function(a){OpenLayers.Protocol.prototype.read.apply(this,arguments);a=OpenLayers.Util.extend({},a);OpenLayers.Util.applyDefaults(a,this.options||{});var b=new OpenLayers.Protocol.Response({requestType:"read"}),
2480 c=OpenLayers.Format.XML.prototype.write.apply(this.format,[this.format.writeNode("wfs:GetFeature",a)]);b.priv=OpenLayers.Request.POST({url:a.url,callback:this.createCallback(this.handleRead,b,a),params:a.params,headers:a.headers,data:c});return b},setFeatureType:function(a){this.featureType=a;this.format.featureType=a},setGeometryName:function(a){this.geometryName=a;this.format.geometryName=a},handleRead:function(a,b){b=OpenLayers.Util.extend({},b);OpenLayers.Util.applyDefaults(b,this.options);if(b.callback){var c=
2481 a.priv;200<=c.status&&300>c.status?(c=this.parseResponse(c,b.readOptions))&&!1!==c.success?(b.readOptions&&"object"==b.readOptions.output?OpenLayers.Util.extend(a,c):a.features=c,a.code=OpenLayers.Protocol.Response.SUCCESS):(a.code=OpenLayers.Protocol.Response.FAILURE,a.error=c):a.code=OpenLayers.Protocol.Response.FAILURE;b.callback.call(b.scope,a)}},parseResponse:function(a,b){var c=a.responseXML;c&&c.documentElement||(c=a.responseText);if(!c||0>=c.length)return null;c=null!==this.readFormat?this.readFormat.read(c):
2482 this.format.read(c,b);if(!this.featureNS){var d=this.readFormat||this.format;this.featureNS=d.featureNS;d.autoConfig=!1;this.geometryName||this.setGeometryName(d.geometryName)}return c},commit:function(a,b){b=OpenLayers.Util.extend({},b);OpenLayers.Util.applyDefaults(b,this.options);var c=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:a});c.priv=OpenLayers.Request.POST({url:b.url,headers:b.headers,data:this.format.write(a,b),callback:this.createCallback(this.handleCommit,c,b)});
2483 return c},handleCommit:function(a,b){if(b.callback){var c=a.priv,d=c.responseXML;d&&d.documentElement||(d=c.responseText);c=this.format.read(d)||{};a.insertIds=c.insertIds||[];c.success?a.code=OpenLayers.Protocol.Response.SUCCESS:(a.code=OpenLayers.Protocol.Response.FAILURE,a.error=c);b.callback.call(b.scope,a)}},filterDelete:function(a,b){b=OpenLayers.Util.extend({},b);OpenLayers.Util.applyDefaults(b,this.options);new OpenLayers.Protocol.Response({requestType:"commit"});var c=this.format.createElementNSPlus("wfs:Transaction",
2484 {attributes:{service:"WFS",version:this.version}}),d=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(b.featureNS?this.featurePrefix+":":"")+b.featureType}});b.featureNS&&d.setAttribute("xmlns:"+this.featurePrefix,b.featureNS);var e=this.format.writeNode("ogc:Filter",a);d.appendChild(e);c.appendChild(d);c=OpenLayers.Format.XML.prototype.write.apply(this.format,[c]);return OpenLayers.Request.POST({url:this.url,callback:b.callback||function(){},data:c})},abort:function(a){a&&a.priv.abort()},
2485 CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{click:{"in":"click",out:"clickout"},mousemove:{"in":"over",out:"out"},dblclick:{"in":"dblclick",out:null},mousedown:{"in":null,out:null},mouseup:{"in":null,out:null},touchstart:{"in":"click",out:"clickout"}},feature:null,lastFeature:null,down:null,up:null,clickTolerance:4,geometryTypes:null,stopClick:!0,stopDown:!0,stopUp:!1,initialize:function(a,b,c,d){OpenLayers.Handler.prototype.initialize.apply(this,[a,c,d]);this.layer=
2486 b},touchstart:function(a){this.startTouch();return OpenLayers.Event.isMultiTouch(a)?!0:this.mousedown(a)},touchmove:function(a){OpenLayers.Event.preventDefault(a)},mousedown:function(a){if(OpenLayers.Event.isLeftClick(a)||OpenLayers.Event.isSingleTouch(a))this.down=a.xy;return this.handle(a)?!this.stopDown:!0},mouseup:function(a){this.up=a.xy;return this.handle(a)?!this.stopUp:!0},click:function(a){return this.handle(a)?!this.stopClick:!0},mousemove:function(a){if(!this.callbacks.over&&!this.callbacks.out)return!0;
2487 this.handle(a);return!0},dblclick:function(a){return!this.handle(a)},geometryTypeMatches:function(a){return null==this.geometryTypes||-1<OpenLayers.Util.indexOf(this.geometryTypes,a.geometry.CLASS_NAME)},handle:function(a){this.feature&&!this.feature.layer&&(this.feature=null);var b=a.type,c=!1,d=!!this.feature,e="click"==b||"dblclick"==b||"touchstart"==b;(this.feature=this.layer.getFeatureFromEvent(a))&&!this.feature.layer&&(this.feature=null);this.lastFeature&&!this.lastFeature.layer&&(this.lastFeature=
2488 null);this.feature?("touchstart"===b&&OpenLayers.Event.preventDefault(a),a=this.feature!=this.lastFeature,this.geometryTypeMatches(this.feature)?(d&&a?(this.lastFeature&&this.triggerCallback(b,"out",[this.lastFeature]),this.triggerCallback(b,"in",[this.feature])):d&&!e||this.triggerCallback(b,"in",[this.feature]),this.lastFeature=this.feature,c=!0):(this.lastFeature&&(d&&a||e)&&this.triggerCallback(b,"out",[this.lastFeature]),this.feature=null)):this.lastFeature&&(d||e)&&this.triggerCallback(b,"out",
2489 [this.lastFeature]);return c},triggerCallback:function(a,b,c){if(b=this.EVENTMAP[a][b])"click"==a&&this.up&&this.down?(Math.sqrt(Math.pow(this.up.x-this.down.x,2)+Math.pow(this.up.y-this.down.y,2))<=this.clickTolerance&&this.callback(b,c),this.up=this.down=null):this.callback(b,c)},activate:function(){var a=!1;OpenLayers.Handler.prototype.activate.apply(this,arguments)&&(this.moveLayerToTop(),this.map.events.on({removelayer:this.handleMapEvents,changelayer:this.handleMapEvents,scope:this}),a=!0);
2490 return a},deactivate:function(){var a=!1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.moveLayerBack(),this.up=this.down=this.lastFeature=this.feature=null,this.map.events.un({removelayer:this.handleMapEvents,changelayer:this.handleMapEvents,scope:this}),a=!0);return a},handleMapEvents:function(a){"removelayer"!=a.type&&"order"!=a.property||this.moveLayerToTop()},moveLayerToTop:function(){var a=Math.max(this.map.Z_INDEX_BASE.Feature-1,this.layer.getZIndex())+1;this.layer.setZIndex(a)},
2491 moveLayerBack:function(){var a=this.layer.getZIndex()-1;a>=this.map.Z_INDEX_BASE.Feature?this.layer.setZIndex(a):this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer))},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:!1,layers:null,display:function(){},getFeatureFromEvent:function(a){for(var b=this.layers,c,d=0;d<b.length;d++)if(c=b[d].getFeatureFromEvent(a))return c},setMap:function(a){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);this.collectRoots();a.events.register("changelayer",this,this.handleChangeLayer)},removeMap:function(a){a.events.unregister("changelayer",this,this.handleChangeLayer);
2492 this.resetRoots();OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments)},collectRoots:function(){for(var a,b=0;b<this.map.layers.length;++b)a=this.map.layers[b],-1!=OpenLayers.Util.indexOf(this.layers,a)&&a.renderer.moveRoot(this.renderer)},resetRoots:function(){for(var a,b=0;b<this.layers.length;++b)a=this.layers[b],this.renderer&&a.renderer.getRenderLayerId()==this.id&&this.renderer.moveRoot(a.renderer)},handleChangeLayer:function(a){var b=a.layer;"order"==a.property&&-1!=OpenLayers.Util.indexOf(this.layers,
2493 b)&&(this.resetRoots(),this.collectRoots())},CLASS_NAME:"OpenLayers.Layer.Vector.RootContainer"});OpenLayers.Control.SelectFeature=OpenLayers.Class(OpenLayers.Control,{multipleKey:null,toggleKey:null,multiple:!1,clickout:!0,toggle:!1,hover:!1,highlightOnly:!1,box:!1,onBeforeSelect:function(){},onSelect:function(){},onUnselect:function(){},scope:null,geometryTypes:null,layer:null,layers:null,callbacks:null,selectStyle:null,renderIntent:"select",handlers:null,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);null===this.scope&&(this.scope=this);this.initLayer(a);var c=
2494 {click:this.clickFeature,clickout:this.clickoutFeature};this.hover&&(c.over=this.overFeature,c.out=this.outFeature);this.callbacks=OpenLayers.Util.extend(c,this.callbacks);this.handlers={feature:new OpenLayers.Handler.Feature(this,this.layer,this.callbacks,{geometryTypes:this.geometryTypes})};this.box&&(this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},{boxDivClassName:"olHandlerBoxSelectFeature"}))},initLayer:function(a){OpenLayers.Util.isArray(a)?(this.layers=a,this.layer=
2495 new OpenLayers.Layer.Vector.RootContainer(this.id+"_container",{layers:a})):this.layer=a},destroy:function(){this.active&&this.layers&&this.map.removeLayer(this.layer);OpenLayers.Control.prototype.destroy.apply(this,arguments);this.layers&&this.layer.destroy()},activate:function(){this.active||(this.layers&&this.map.addLayer(this.layer),this.handlers.feature.activate(),this.box&&this.handlers.box&&this.handlers.box.activate());return OpenLayers.Control.prototype.activate.apply(this,arguments)},deactivate:function(){this.active&&
2496 (this.handlers.feature.deactivate(),this.handlers.box&&this.handlers.box.deactivate(),this.layers&&this.map.removeLayer(this.layer));return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},unselectAll:function(a){var b=this.layers||[this.layer],c,d,e,f;for(e=0;e<b.length;++e)if(c=b[e],f=0,null!=c.selectedFeatures)for(;c.selectedFeatures.length>f;)d=c.selectedFeatures[f],a&&a.except==d?++f:this.unselect(d)},clickFeature:function(a){this.hover||(-1<OpenLayers.Util.indexOf(a.layer.selectedFeatures,
2497 a)?this.toggleSelect()?this.unselect(a):this.multipleSelect()||this.unselectAll({except:a}):(this.multipleSelect()||this.unselectAll({except:a}),this.select(a)))},multipleSelect:function(){return this.multiple||this.handlers.feature.evt&&this.handlers.feature.evt[this.multipleKey]},toggleSelect:function(){return this.toggle||this.handlers.feature.evt&&this.handlers.feature.evt[this.toggleKey]},clickoutFeature:function(a){!this.hover&&this.clickout&&this.unselectAll()},overFeature:function(a){var b=
2498 a.layer;this.hover&&(this.highlightOnly?this.highlight(a):-1==OpenLayers.Util.indexOf(b.selectedFeatures,a)&&this.select(a))},outFeature:function(a){if(this.hover)if(this.highlightOnly){if(a._lastHighlighter==this.id)if(a._prevHighlighter&&a._prevHighlighter!=this.id){delete a._lastHighlighter;var b=this.map.getControl(a._prevHighlighter);b&&b.highlight(a)}else this.unhighlight(a)}else this.unselect(a)},highlight:function(a){var b=a.layer;!1!==this.events.triggerEvent("beforefeaturehighlighted",{feature:a})&&
2499 (a._prevHighlighter=a._lastHighlighter,a._lastHighlighter=this.id,b.drawFeature(a,this.selectStyle||this.renderIntent),this.events.triggerEvent("featurehighlighted",{feature:a}))},unhighlight:function(a){var b=a.layer;void 0==a._prevHighlighter?delete a._lastHighlighter:(a._prevHighlighter!=this.id&&(a._lastHighlighter=a._prevHighlighter),delete a._prevHighlighter);b.drawFeature(a,a.style||a.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:a})},select:function(a){var b=
2500 this.onBeforeSelect.call(this.scope,a),c=a.layer;!1!==b&&(b=c.events.triggerEvent("beforefeatureselected",{feature:a}),!1!==b&&(c.selectedFeatures.push(a),this.highlight(a),this.handlers.feature.lastFeature||(this.handlers.feature.lastFeature=c.selectedFeatures[0]),c.events.triggerEvent("featureselected",{feature:a}),this.onSelect.call(this.scope,a)))},unselect:function(a){var b=a.layer;this.unhighlight(a);OpenLayers.Util.removeItem(b.selectedFeatures,a);b.events.triggerEvent("featureunselected",
2501 {feature:a});this.onUnselect.call(this.scope,a)},selectBox:function(a){if(a instanceof OpenLayers.Bounds){var b=this.map.getLonLatFromPixel({x:a.left,y:a.bottom});a=this.map.getLonLatFromPixel({x:a.right,y:a.top});b=new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat);this.multipleSelect()||this.unselectAll();a=this.multiple;this.multiple=!0;var c=this.layers||[this.layer];this.events.triggerEvent("boxselectionstart",{layers:c});for(var d,e=0;e<c.length;++e){d=c[e];for(var f=0,g=d.features.length;f<g;++f){var h=
2502 d.features[f];h.getVisibility()&&(null==this.geometryTypes||-1<OpenLayers.Util.indexOf(this.geometryTypes,h.geometry.CLASS_NAME))&&b.toGeometry().intersects(h.geometry)&&-1==OpenLayers.Util.indexOf(d.selectedFeatures,h)&&this.select(h)}}this.multiple=a;this.events.triggerEvent("boxselectionend",{layers:c})}},setMap:function(a){this.handlers.feature.setMap(a);this.box&&this.handlers.box.setMap(a);OpenLayers.Control.prototype.setMap.apply(this,arguments)},setLayer:function(a){var b=this.active;this.unselectAll();
2503 this.deactivate();this.layers&&(this.layer.destroy(),this.layers=null);this.initLayer(a);this.handlers.feature.layer=this.layer;b&&this.activate()},CLASS_NAME:"OpenLayers.Control.SelectFeature"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:!1,citeCompliant:!1,mouseDown:!1,stoppedDown:null,lastDown:null,lastUp:null,persist:!1,stopDown:!1,stopUp:!1,layerOptions:null,pixelTolerance:5,lastTouchPx:null,initialize:function(a,b,c){c&&c.layerOptions&&c.layerOptions.styleMap||(this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style["default"],{}));OpenLayers.Handler.prototype.initialize.apply(this,arguments)},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,
2504 arguments))return!1;var a=OpenLayers.Util.extend({displayInLayerSwitcher:!1,calculateInRange:OpenLayers.Function.True,wrapDateLine:this.citeCompliant},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,a);this.map.addLayer(this.layer);return!0},createFeature:function(a){a=this.layer.getLonLatFromViewPortPx(a);a=new OpenLayers.Geometry.Point(a.lon,a.lat);this.point=new OpenLayers.Feature.Vector(a);this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();
2505 this.layer.addFeatures([this.point],{silent:!0})},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments))return!1;this.cancel();null!=this.layer.map&&(this.destroyFeature(!0),this.layer.destroy(!1));this.layer=null;return!0},destroyFeature:function(a){!this.layer||!a&&this.persist||this.layer.destroyFeatures();this.point=null},destroyPersistedFeature:function(){var a=this.layer;a&&1<a.features.length&&this.layer.features[0].destroy()},finalize:function(a){this.mouseDown=
2506 !1;this.lastTouchPx=this.lastUp=this.lastDown=null;this.callback(a?"cancel":"done",[this.geometryClone()]);this.destroyFeature(a)},cancel:function(){this.finalize(!0)},click:function(a){OpenLayers.Event.stop(a);return!1},dblclick:function(a){OpenLayers.Event.stop(a);return!1},modifyFeature:function(a){this.point||this.createFeature(a);a=this.layer.getLonLatFromViewPortPx(a);this.point.geometry.x=a.lon;this.point.geometry.y=a.lat;this.callback("modify",[this.point.geometry,this.point,!1]);this.point.geometry.clearBounds();
2507 this.drawFeature()},drawFeature:function(){this.layer.drawFeature(this.point,this.style)},getGeometry:function(){var a=this.point&&this.point.geometry;a&&this.multi&&(a=new OpenLayers.Geometry.MultiPoint([a]));return a},geometryClone:function(){var a=this.getGeometry();return a&&a.clone()},mousedown:function(a){return this.down(a)},touchstart:function(a){this.startTouch();this.lastTouchPx=a.xy;return this.down(a)},mousemove:function(a){return this.move(a)},touchmove:function(a){this.lastTouchPx=a.xy;
2508 return this.move(a)},mouseup:function(a){return this.up(a)},touchend:function(a){a.xy=this.lastTouchPx;return this.up(a)},down:function(a){this.mouseDown=!0;this.lastDown=a.xy;this.touch||this.modifyFeature(a.xy);this.stoppedDown=this.stopDown;return!this.stopDown},move:function(a){this.touch||this.mouseDown&&!this.stoppedDown||this.modifyFeature(a.xy);return!0},up:function(a){this.mouseDown=!1;this.stoppedDown=this.stopDown;if(!this.checkModifiers(a)||this.lastUp&&this.lastUp.equals(a.xy)||!this.lastDown||
2509 !this.passesTolerance(this.lastDown,a.xy,this.pixelTolerance))return!0;this.touch&&this.modifyFeature(a.xy);this.persist&&this.destroyPersistedFeature();this.lastUp=a.xy;this.finalize();return!this.stopUp},mouseout:function(a){OpenLayers.Util.mouseLeft(a,this.map.viewPortDiv)&&(this.stoppedDown=this.stopDown,this.mouseDown=!1)},passesTolerance:function(a,b,c){var d=!0;null!=c&&a&&b&&a.distanceTo(b)>c&&(d=!1);return d},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,maxVertices:null,doubleTouchTolerance:20,freehand:!1,freehandToggle:"shiftKey",timerId:null,redoStack:null,createFeature:function(a){a=this.layer.getLonLatFromViewPortPx(a);a=new OpenLayers.Geometry.Point(a.lon,a.lat);this.point=new OpenLayers.Feature.Vector(a);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([this.point.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);
2510 this.point.geometry.clearBounds();this.layer.addFeatures([this.line,this.point],{silent:!0})},destroyFeature:function(a){OpenLayers.Handler.Point.prototype.destroyFeature.call(this,a);this.line=null},destroyPersistedFeature:function(){var a=this.layer;a&&2<a.features.length&&this.layer.features[0].destroy()},removePoint:function(){this.point&&this.layer.removeFeatures([this.point])},addPoint:function(a){this.layer.removeFeatures([this.point]);a=this.layer.getLonLatFromViewPortPx(a);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(a.lon,
2511 a.lat));this.line.geometry.addComponent(this.point.geometry,this.line.geometry.components.length);this.layer.addFeatures([this.point]);this.callback("point",[this.point.geometry,this.getGeometry()]);this.callback("modify",[this.point.geometry,this.getSketch()]);this.drawFeature();delete this.redoStack},insertXY:function(a,b){this.line.geometry.addComponent(new OpenLayers.Geometry.Point(a,b),this.getCurrentPointIndex());this.drawFeature();delete this.redoStack},insertDeltaXY:function(a,b){var c=this.getCurrentPointIndex()-
2512 1,c=this.line.geometry.components[c];!c||(isNaN(c.x)||isNaN(c.y))||this.insertXY(c.x+a,c.y+b)},insertDirectionLength:function(a,b){a*=Math.PI/180;var c=b*Math.cos(a),d=b*Math.sin(a);this.insertDeltaXY(c,d)},insertDeflectionLength:function(a,b){var c=this.getCurrentPointIndex()-1;if(0<c){var d=this.line.geometry.components[c],c=this.line.geometry.components[c-1],d=Math.atan2(d.y-c.y,d.x-c.x);this.insertDirectionLength(180*d/Math.PI+a,b)}},getCurrentPointIndex:function(){return this.line.geometry.components.length-
2513 1},undo:function(){var a=this.line.geometry,b=a.components,c=this.getCurrentPointIndex()-1,d=b[c],e=a.removeComponent(d);e&&(this.touch&&0<c&&(b=a.components,a=b[c-1],c=this.getCurrentPointIndex(),b=b[c],b.x=a.x,b.y=a.y),this.redoStack||(this.redoStack=[]),this.redoStack.push(d),this.drawFeature());return e},redo:function(){var a=this.redoStack&&this.redoStack.pop();a&&(this.line.geometry.addComponent(a,this.getCurrentPointIndex()),this.drawFeature());return!!a},freehandMode:function(a){return this.freehandToggle&&
2514 a[this.freehandToggle]?!this.freehand:this.freehand},modifyFeature:function(a,b){this.line||this.createFeature(a);var c=this.layer.getLonLatFromViewPortPx(a);this.point.geometry.x=c.lon;this.point.geometry.y=c.lat;this.callback("modify",[this.point.geometry,this.getSketch(),b]);this.point.geometry.clearBounds();this.drawFeature()},drawFeature:function(){this.layer.drawFeature(this.line,this.style);this.layer.drawFeature(this.point,this.style)},getSketch:function(){return this.line},getGeometry:function(){var a=
2515 this.line&&this.line.geometry;a&&this.multi&&(a=new OpenLayers.Geometry.MultiLineString([a]));return a},touchstart:function(a){if(this.timerId&&this.passesTolerance(this.lastTouchPx,a.xy,this.doubleTouchTolerance))return this.finishGeometry(),window.clearTimeout(this.timerId),this.timerId=null,!1;this.timerId&&(window.clearTimeout(this.timerId),this.timerId=null);this.timerId=window.setTimeout(OpenLayers.Function.bind(function(){this.timerId=null},this),300);return OpenLayers.Handler.Point.prototype.touchstart.call(this,
2516 a)},down:function(a){var b=this.stopDown;this.freehandMode(a)&&(b=!0,this.touch&&(this.modifyFeature(a.xy,!!this.lastUp),OpenLayers.Event.stop(a)));this.touch||this.lastDown&&this.passesTolerance(this.lastDown,a.xy,this.pixelTolerance)||this.modifyFeature(a.xy,!!this.lastUp);this.mouseDown=!0;this.lastDown=a.xy;this.stoppedDown=b;return!b},move:function(a){if(this.stoppedDown&&this.freehandMode(a))return this.persist&&this.destroyPersistedFeature(),this.maxVertices&&this.line&&this.line.geometry.components.length===
2517 this.maxVertices?(this.removePoint(),this.finalize()):this.addPoint(a.xy),!1;this.touch||this.mouseDown&&!this.stoppedDown||this.modifyFeature(a.xy,!!this.lastUp);return!0},up:function(a){!this.mouseDown||this.lastUp&&this.lastUp.equals(a.xy)||(this.stoppedDown&&this.freehandMode(a)?(this.persist&&this.destroyPersistedFeature(),this.removePoint(),this.finalize()):this.passesTolerance(this.lastDown,a.xy,this.pixelTolerance)&&(this.touch&&this.modifyFeature(a.xy),null==this.lastUp&&this.persist&&this.destroyPersistedFeature(),
2518 this.addPoint(a.xy),this.lastUp=a.xy,this.line.geometry.components.length===this.maxVertices+1&&this.finishGeometry()));this.stoppedDown=this.stopDown;this.mouseDown=!1;return!this.stopUp},finishGeometry:function(){this.line.geometry.removeComponent(this.line.geometry.components[this.line.geometry.components.length-1]);this.removePoint();this.finalize()},dblclick:function(a){this.freehandMode(a)||this.finishGeometry();return!1},CLASS_NAME:"OpenLayers.Handler.Path"});OpenLayers.Spherical=OpenLayers.Spherical||{};OpenLayers.Spherical.DEFAULT_RADIUS=6378137;OpenLayers.Spherical.computeDistanceBetween=function(a,b,c){c=c||OpenLayers.Spherical.DEFAULT_RADIUS;var d=Math.sin(Math.PI*(b.lon-a.lon)/360),e=Math.sin(Math.PI*(b.lat-a.lat)/360);a=e*e+d*d*Math.cos(Math.PI*a.lat/180)*Math.cos(Math.PI*b.lat/180);return 2*c*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))};
2519 OpenLayers.Spherical.computeHeading=function(a,b){var c=Math.sin(Math.PI*(a.lon-b.lon)/180)*Math.cos(Math.PI*b.lat/180),d=Math.cos(Math.PI*a.lat/180)*Math.sin(Math.PI*b.lat/180)-Math.sin(Math.PI*a.lat/180)*Math.cos(Math.PI*b.lat/180)*Math.cos(Math.PI*(a.lon-b.lon)/180);return 180*Math.atan2(c,d)/Math.PI};OpenLayers.Control.CacheWrite=OpenLayers.Class(OpenLayers.Control,{layers:null,imageFormat:"image/png",quotaRegEx:/quota/i,setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);var b,c=this.layers||a.layers;for(b=c.length-1;0<=b;--b)this.addLayer({layer:c[b]});if(!this.layers)a.events.on({addlayer:this.addLayer,removeLayer:this.removeLayer,scope:this})},addLayer:function(a){a.layer.events.on({tileloadstart:this.makeSameOrigin,tileloaded:this.onTileLoaded,scope:this})},removeLayer:function(a){a.layer.events.un({tileloadstart:this.makeSameOrigin,
2520 tileloaded:this.onTileLoaded,scope:this})},makeSameOrigin:function(a){if(this.active&&(a=a.tile,a instanceof OpenLayers.Tile.Image&&!a.crossOriginKeyword&&"data:"!==a.url.substr(0,5))){var b=OpenLayers.Request.makeSameOrigin(a.url,OpenLayers.ProxyHost);OpenLayers.Control.CacheWrite.urlMap[b]=a.url;a.url=b}},onTileLoaded:function(a){this.active&&(!a.aborted&&a.tile instanceof OpenLayers.Tile.Image&&"data:"!==a.tile.url.substr(0,5))&&(this.cache({tile:a.tile}),delete OpenLayers.Control.CacheWrite.urlMap[a.tile.url])},
2521 cache:function(a){if(window.localStorage){a=a.tile;try{var b=a.getCanvasContext();b&&window.localStorage.setItem("olCache_"+(OpenLayers.Control.CacheWrite.urlMap[a.url]||a.url),b.canvas.toDataURL(this.imageFormat))}catch(c){(b=c.name||c.message)&&this.quotaRegEx.test(b)?this.events.triggerEvent("cachefull",{tile:a}):OpenLayers.Console.error(c.toString())}}},destroy:function(){if(this.layers||this.map){var a,b=this.layers||this.map.layers;for(a=b.length-1;0<=a;--a)this.removeLayer({layer:b[a]})}this.map&&
2522 this.map.events.un({addlayer:this.addLayer,removeLayer:this.removeLayer,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments)},CLASS_NAME:"OpenLayers.Control.CacheWrite"});OpenLayers.Control.CacheWrite.clearCache=function(){if(window.localStorage){var a,b;for(a=window.localStorage.length-1;0<=a;--a)b=window.localStorage.key(a),"olCache_"===b.substr(0,8)&&window.localStorage.removeItem(b)}};OpenLayers.Control.CacheWrite.urlMap={};OpenLayers.Format.Context=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{layerOptions:null,layerParams:null,read:function(a,b){var c=OpenLayers.Format.XML.VersionedOGC.prototype.read.apply(this,arguments);if(b&&b.map)if(this.context=c,b.map instanceof OpenLayers.Map)c=this.mergeContextToMap(c,b.map);else{var d=b.map;if(OpenLayers.Util.isElement(d)||"string"==typeof d)d={div:d};c=this.contextToMap(c,d)}return c},getLayerFromContext:function(a){var b,c,d={queryable:a.queryable,visibility:a.visibility,
2523 maxExtent:a.maxExtent,metadata:OpenLayers.Util.applyDefaults(a.metadata,{styles:a.styles,formats:a.formats,"abstract":a["abstract"],dataURL:a.dataURL}),numZoomLevels:a.numZoomLevels,units:a.units,isBaseLayer:a.isBaseLayer,opacity:a.opacity,displayInLayerSwitcher:a.displayInLayerSwitcher,singleTile:a.singleTile,tileSize:a.tileSize?new OpenLayers.Size(a.tileSize.width,a.tileSize.height):void 0,minScale:a.minScale||a.maxScaleDenominator,maxScale:a.maxScale||a.minScaleDenominator,srs:a.srs,dimensions:a.dimensions,
2524 metadataURL:a.metadataURL};this.layerOptions&&OpenLayers.Util.applyDefaults(d,this.layerOptions);var e={layers:a.name,transparent:a.transparent,version:a.version};if(a.formats&&0<a.formats.length)for(e.format=a.formats[0].value,b=0,c=a.formats.length;b<c;b++){var f=a.formats[b];if(!0==f.current){e.format=f.value;break}}if(a.styles&&0<a.styles.length)for(b=0,c=a.styles.length;b<c;b++)if(f=a.styles[b],!0==f.current){f.href?e.sld=f.href:f.body?e.sld_body=f.body:e.styles=f.name;break}this.layerParams&&
2525 OpenLayers.Util.applyDefaults(e,this.layerParams);b=null;c=a.service;c==OpenLayers.Format.Context.serviceTypes.WFS?(d.strategies=[new OpenLayers.Strategy.BBOX],d.protocol=new OpenLayers.Protocol.WFS({url:a.url,featurePrefix:a.name.split(":")[0],featureType:a.name.split(":").pop()}),b=new OpenLayers.Layer.Vector(a.title||a.name,d)):c==OpenLayers.Format.Context.serviceTypes.KML?(d.strategies=[new OpenLayers.Strategy.Fixed],d.protocol=new OpenLayers.Protocol.HTTP({url:a.url,format:new OpenLayers.Format.KML}),
2526 b=new OpenLayers.Layer.Vector(a.title||a.name,d)):c==OpenLayers.Format.Context.serviceTypes.GML?(d.strategies=[new OpenLayers.Strategy.Fixed],d.protocol=new OpenLayers.Protocol.HTTP({url:a.url,format:new OpenLayers.Format.GML}),b=new OpenLayers.Layer.Vector(a.title||a.name,d)):a.features?(b=new OpenLayers.Layer.Vector(a.title||a.name,d),b.addFeatures(a.features)):!0!==a.categoryLayer&&(b=new OpenLayers.Layer.WMS(a.title||a.name,a.url,e,d));return b},getLayersFromContext:function(a){for(var b=[],c=
2527 0,d=a.length;c<d;c++){var e=this.getLayerFromContext(a[c]);null!==e&&b.push(e)}return b},contextToMap:function(a,b){b=OpenLayers.Util.applyDefaults({maxExtent:a.maxExtent,projection:a.projection,units:a.units},b);b.maxExtent&&(b.maxResolution=b.maxExtent.getWidth()/OpenLayers.Map.TILE_WIDTH);b.metadata={contactInformation:a.contactInformation,"abstract":a["abstract"],keywords:a.keywords,logo:a.logo,descriptionURL:a.descriptionURL};var c=new OpenLayers.Map(b);c.addLayers(this.getLayersFromContext(a.layersContext));
2528 c.setCenter(a.bounds.getCenterLonLat(),c.getZoomForExtent(a.bounds,!0));return c},mergeContextToMap:function(a,b){b.addLayers(this.getLayersFromContext(a.layersContext));return b},write:function(a,b){a=this.toContext(a);return OpenLayers.Format.XML.VersionedOGC.prototype.write.apply(this,arguments)},CLASS_NAME:"OpenLayers.Format.Context"});
2529 OpenLayers.Format.Context.serviceTypes={WMS:"urn:ogc:serviceType:WMS",WFS:"urn:ogc:serviceType:WFS",WCS:"urn:ogc:serviceType:WCS",GML:"urn:ogc:serviceType:GML",SLD:"urn:ogc:serviceType:SLD",FES:"urn:ogc:serviceType:FES",KML:"urn:ogc:serviceType:KML"};OpenLayers.Format.WMC=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"1.1.0",layerToContext:function(a){var b=this.getParser(),c={queryable:a.queryable,visibility:a.visibility,name:a.params.LAYERS,title:a.name,"abstract":a.metadata["abstract"],dataURL:a.metadata.dataURL,metadataURL:a.metadataURL,server:{version:a.params.VERSION,url:a.url},maxExtent:a.maxExtent,transparent:a.params.TRANSPARENT,numZoomLevels:a.numZoomLevels,units:a.units,isBaseLayer:a.isBaseLayer,opacity:1==a.opacity?void 0:
2530 a.opacity,displayInLayerSwitcher:a.displayInLayerSwitcher,singleTile:a.singleTile,tileSize:a.singleTile||!a.tileSize?void 0:{width:a.tileSize.w,height:a.tileSize.h},minScale:a.options.resolutions||a.options.scales||a.options.maxResolution||a.options.minScale?a.minScale:void 0,maxScale:a.options.resolutions||a.options.scales||a.options.minResolution||a.options.maxScale?a.maxScale:void 0,formats:[],styles:[],srs:a.srs,dimensions:a.dimensions};a.metadata.servertitle&&(c.server.title=a.metadata.servertitle);
2531 if(a.metadata.formats&&0<a.metadata.formats.length)for(var d=0,e=a.metadata.formats.length;d<e;d++){var f=a.metadata.formats[d];c.formats.push({value:f.value,current:f.value==a.params.FORMAT})}else c.formats.push({value:a.params.FORMAT,current:!0});if(a.metadata.styles&&0<a.metadata.styles.length)for(d=0,e=a.metadata.styles.length;d<e;d++)b=a.metadata.styles[d],b.current=b.href==a.params.SLD||b.body==a.params.SLD_BODY||b.name==a.params.STYLES?!0:!1,c.styles.push(b);else c.styles.push({href:a.params.SLD,
2532 body:a.params.SLD_BODY,name:a.params.STYLES||b.defaultStyleName,title:b.defaultStyleTitle,current:!0});return c},toContext:function(a){var b={},c=a.layers;if("OpenLayers.Map"==a.CLASS_NAME){var d=a.metadata||{};b.size=a.getSize();b.bounds=a.getExtent();b.projection=a.projection;b.title=a.title;b.keywords=d.keywords;b["abstract"]=d["abstract"];b.logo=d.logo;b.descriptionURL=d.descriptionURL;b.contactInformation=d.contactInformation;b.maxExtent=a.maxExtent}else OpenLayers.Util.applyDefaults(b,a),void 0!=
2533 b.layers&&delete b.layers;void 0==b.layersContext&&(b.layersContext=[]);if(void 0!=c&&OpenLayers.Util.isArray(c))for(a=0,d=c.length;a<d;a++){var e=c[a];e instanceof OpenLayers.Layer.WMS&&b.layersContext.push(this.layerToContext(e))}return b},CLASS_NAME:"OpenLayers.Format.WMC"});OpenLayers.Format.WMC.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ol:"http://openlayers.org/context",wmc:"http://www.opengis.net/context",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"",getNamespacePrefix:function(a){var b=null;if(null==a)b=this.namespaces[this.defaultPrefix];else for(b in this.namespaces)if(this.namespaces[b]==a)break;return b},defaultPrefix:"wmc",rootPrefix:null,defaultStyleName:"",
2534 defaultStyleTitle:"Default",initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a=a.documentElement;this.rootPrefix=a.prefix;var b={version:a.getAttribute("version")};this.runChildNodes(b,a);return b},runChildNodes:function(a,b){for(var c=b.childNodes,d,e,f,g=0,h=c.length;g<h;++g)d=c[g],1==d.nodeType&&(e=this.getNamespacePrefix(d.namespaceURI),f=d.nodeName.split(":").pop(),
2535 (e=this["read_"+e+"_"+f])&&e.apply(this,[a,d]))},read_wmc_General:function(a,b){this.runChildNodes(a,b)},read_wmc_BoundingBox:function(a,b){a.projection=b.getAttribute("SRS");a.bounds=new OpenLayers.Bounds(b.getAttribute("minx"),b.getAttribute("miny"),b.getAttribute("maxx"),b.getAttribute("maxy"))},read_wmc_LayerList:function(a,b){a.layersContext=[];this.runChildNodes(a,b)},read_wmc_Layer:function(a,b){var c={visibility:"1"!=b.getAttribute("hidden"),queryable:"1"==b.getAttribute("queryable"),formats:[],
2536 styles:[],metadata:{}};this.runChildNodes(c,b);a.layersContext.push(c)},read_wmc_Extension:function(a,b){this.runChildNodes(a,b)},read_ol_units:function(a,b){a.units=this.getChildValue(b)},read_ol_maxExtent:function(a,b){var c=new OpenLayers.Bounds(b.getAttribute("minx"),b.getAttribute("miny"),b.getAttribute("maxx"),b.getAttribute("maxy"));a.maxExtent=c},read_ol_transparent:function(a,b){a.transparent=this.getChildValue(b)},read_ol_numZoomLevels:function(a,b){a.numZoomLevels=parseInt(this.getChildValue(b))},
2537 read_ol_opacity:function(a,b){a.opacity=parseFloat(this.getChildValue(b))},read_ol_singleTile:function(a,b){a.singleTile="true"==this.getChildValue(b)},read_ol_tileSize:function(a,b){var c={width:b.getAttribute("width"),height:b.getAttribute("height")};a.tileSize=c},read_ol_isBaseLayer:function(a,b){a.isBaseLayer="true"==this.getChildValue(b)},read_ol_displayInLayerSwitcher:function(a,b){a.displayInLayerSwitcher="true"==this.getChildValue(b)},read_wmc_Server:function(a,b){a.version=b.getAttribute("version");
2538 a.url=this.getOnlineResource_href(b);a.metadata.servertitle=b.getAttribute("title")},read_wmc_FormatList:function(a,b){this.runChildNodes(a,b)},read_wmc_Format:function(a,b){var c={value:this.getChildValue(b)};"1"==b.getAttribute("current")&&(c.current=!0);a.formats.push(c)},read_wmc_StyleList:function(a,b){this.runChildNodes(a,b)},read_wmc_Style:function(a,b){var c={};this.runChildNodes(c,b);"1"==b.getAttribute("current")&&(c.current=!0);a.styles.push(c)},read_wmc_SLD:function(a,b){this.runChildNodes(a,
2539 b)},read_sld_StyledLayerDescriptor:function(a,b){var c=OpenLayers.Format.XML.prototype.write.apply(this,[b]);a.body=c},read_sld_FeatureTypeStyle:function(a,b){var c=OpenLayers.Format.XML.prototype.write.apply(this,[b]);a.body=c},read_wmc_OnlineResource:function(a,b){a.href=this.getAttributeNS(b,this.namespaces.xlink,"href")},read_wmc_Name:function(a,b){var c=this.getChildValue(b);c&&(a.name=c)},read_wmc_Title:function(a,b){var c=this.getChildValue(b);c&&(a.title=c)},read_wmc_MetadataURL:function(a,
2540 b){a.metadataURL=this.getOnlineResource_href(b)},read_wmc_KeywordList:function(a,b){a.keywords=[];this.runChildNodes(a.keywords,b)},read_wmc_Keyword:function(a,b){a.push(this.getChildValue(b))},read_wmc_Abstract:function(a,b){var c=this.getChildValue(b);c&&(a["abstract"]=c)},read_wmc_LogoURL:function(a,b){a.logo={width:b.getAttribute("width"),height:b.getAttribute("height"),format:b.getAttribute("format"),href:this.getOnlineResource_href(b)}},read_wmc_DescriptionURL:function(a,b){a.descriptionURL=
2541 this.getOnlineResource_href(b)},read_wmc_ContactInformation:function(a,b){var c={};this.runChildNodes(c,b);a.contactInformation=c},read_wmc_ContactPersonPrimary:function(a,b){var c={};this.runChildNodes(c,b);a.personPrimary=c},read_wmc_ContactPerson:function(a,b){var c=this.getChildValue(b);c&&(a.person=c)},read_wmc_ContactOrganization:function(a,b){var c=this.getChildValue(b);c&&(a.organization=c)},read_wmc_ContactPosition:function(a,b){var c=this.getChildValue(b);c&&(a.position=c)},read_wmc_ContactAddress:function(a,
2542 b){var c={};this.runChildNodes(c,b);a.contactAddress=c},read_wmc_AddressType:function(a,b){var c=this.getChildValue(b);c&&(a.type=c)},read_wmc_Address:function(a,b){var c=this.getChildValue(b);c&&(a.address=c)},read_wmc_City:function(a,b){var c=this.getChildValue(b);c&&(a.city=c)},read_wmc_StateOrProvince:function(a,b){var c=this.getChildValue(b);c&&(a.stateOrProvince=c)},read_wmc_PostCode:function(a,b){var c=this.getChildValue(b);c&&(a.postcode=c)},read_wmc_Country:function(a,b){var c=this.getChildValue(b);
2543 c&&(a.country=c)},read_wmc_ContactVoiceTelephone:function(a,b){var c=this.getChildValue(b);c&&(a.phone=c)},read_wmc_ContactFacsimileTelephone:function(a,b){var c=this.getChildValue(b);c&&(a.fax=c)},read_wmc_ContactElectronicMailAddress:function(a,b){var c=this.getChildValue(b);c&&(a.email=c)},read_wmc_DataURL:function(a,b){a.dataURL=this.getOnlineResource_href(b)},read_wmc_LegendURL:function(a,b){var c={width:b.getAttribute("width"),height:b.getAttribute("height"),format:b.getAttribute("format"),
2544 href:this.getOnlineResource_href(b)};a.legend=c},read_wmc_DimensionList:function(a,b){a.dimensions={};this.runChildNodes(a.dimensions,b)},read_wmc_Dimension:function(a,b){var c={name:b.getAttribute("name").toLowerCase(),units:b.getAttribute("units")||"",unitSymbol:b.getAttribute("unitSymbol")||"",userValue:b.getAttribute("userValue")||"",nearestValue:"1"===b.getAttribute("nearestValue"),multipleValues:"1"===b.getAttribute("multipleValues"),current:"1"===b.getAttribute("current"),"default":b.getAttribute("default")||
2545 ""},d=this.getChildValue(b);c.values=d.split(",");a[c.name]=c},write:function(a,b){var c=this.createElementDefaultNS("ViewContext");this.setAttributes(c,{version:this.VERSION,id:b&&"string"==typeof b.id?b.id:OpenLayers.Util.createUniqueID("OpenLayers_Context_")});this.setAttributeNS(c,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);c.appendChild(this.write_wmc_General(a));c.appendChild(this.write_wmc_LayerList(a));return OpenLayers.Format.XML.prototype.write.apply(this,[c])},createElementDefaultNS:function(a,
2546 b,c){a=this.createElementNS(this.namespaces[this.defaultPrefix],a);b&&a.appendChild(this.createTextNode(b));c&&this.setAttributes(a,c);return a},setAttributes:function(a,b){var c,d;for(d in b)c=b[d].toString(),c.match(/[A-Z]/)?this.setAttributeNS(a,null,d,c):a.setAttribute(d,c)},write_wmc_General:function(a){var b=this.createElementDefaultNS("General");a.size&&b.appendChild(this.createElementDefaultNS("Window",null,{width:a.size.w,height:a.size.h}));var c=a.bounds;b.appendChild(this.createElementDefaultNS("BoundingBox",
2547 null,{minx:c.left.toPrecision(18),miny:c.bottom.toPrecision(18),maxx:c.right.toPrecision(18),maxy:c.top.toPrecision(18),SRS:a.projection}));b.appendChild(this.createElementDefaultNS("Title",a.title));a.keywords&&b.appendChild(this.write_wmc_KeywordList(a.keywords));a["abstract"]&&b.appendChild(this.createElementDefaultNS("Abstract",a["abstract"]));a.logo&&b.appendChild(this.write_wmc_URLType("LogoURL",a.logo.href,a.logo));a.descriptionURL&&b.appendChild(this.write_wmc_URLType("DescriptionURL",a.descriptionURL));
2548 a.contactInformation&&b.appendChild(this.write_wmc_ContactInformation(a.contactInformation));b.appendChild(this.write_ol_MapExtension(a));return b},write_wmc_KeywordList:function(a){for(var b=this.createElementDefaultNS("KeywordList"),c=0,d=a.length;c<d;c++)b.appendChild(this.createElementDefaultNS("Keyword",a[c]));return b},write_wmc_ContactInformation:function(a){var b=this.createElementDefaultNS("ContactInformation");a.personPrimary&&b.appendChild(this.write_wmc_ContactPersonPrimary(a.personPrimary));
2549 a.position&&b.appendChild(this.createElementDefaultNS("ContactPosition",a.position));a.contactAddress&&b.appendChild(this.write_wmc_ContactAddress(a.contactAddress));a.phone&&b.appendChild(this.createElementDefaultNS("ContactVoiceTelephone",a.phone));a.fax&&b.appendChild(this.createElementDefaultNS("ContactFacsimileTelephone",a.fax));a.email&&b.appendChild(this.createElementDefaultNS("ContactElectronicMailAddress",a.email));return b},write_wmc_ContactPersonPrimary:function(a){var b=this.createElementDefaultNS("ContactPersonPrimary");
2550 a.person&&b.appendChild(this.createElementDefaultNS("ContactPerson",a.person));a.organization&&b.appendChild(this.createElementDefaultNS("ContactOrganization",a.organization));return b},write_wmc_ContactAddress:function(a){var b=this.createElementDefaultNS("ContactAddress");a.type&&b.appendChild(this.createElementDefaultNS("AddressType",a.type));a.address&&b.appendChild(this.createElementDefaultNS("Address",a.address));a.city&&b.appendChild(this.createElementDefaultNS("City",a.city));a.stateOrProvince&&
2551 b.appendChild(this.createElementDefaultNS("StateOrProvince",a.stateOrProvince));a.postcode&&b.appendChild(this.createElementDefaultNS("PostCode",a.postcode));a.country&&b.appendChild(this.createElementDefaultNS("Country",a.country));return b},write_ol_MapExtension:function(a){var b=this.createElementDefaultNS("Extension");if(a=a.maxExtent){var c=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(c,{minx:a.left.toPrecision(18),miny:a.bottom.toPrecision(18),maxx:a.right.toPrecision(18),
2552 maxy:a.top.toPrecision(18)});b.appendChild(c)}return b},write_wmc_LayerList:function(a){for(var b=this.createElementDefaultNS("LayerList"),c=0,d=a.layersContext.length;c<d;++c)b.appendChild(this.write_wmc_Layer(a.layersContext[c]));return b},write_wmc_Layer:function(a){var b=this.createElementDefaultNS("Layer",null,{queryable:a.queryable?"1":"0",hidden:a.visibility?"0":"1"});b.appendChild(this.write_wmc_Server(a));b.appendChild(this.createElementDefaultNS("Name",a.name));b.appendChild(this.createElementDefaultNS("Title",
2553 a.title));a["abstract"]&&b.appendChild(this.createElementDefaultNS("Abstract",a["abstract"]));a.dataURL&&b.appendChild(this.write_wmc_URLType("DataURL",a.dataURL));a.metadataURL&&b.appendChild(this.write_wmc_URLType("MetadataURL",a.metadataURL));return b},write_wmc_LayerExtension:function(a){var b=this.createElementDefaultNS("Extension"),c=a.maxExtent,d=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(d,{minx:c.left.toPrecision(18),miny:c.bottom.toPrecision(18),maxx:c.right.toPrecision(18),
2554 maxy:c.top.toPrecision(18)});b.appendChild(d);a.tileSize&&!a.singleTile&&(c=this.createElementNS(this.namespaces.ol,"ol:tileSize"),this.setAttributes(c,a.tileSize),b.appendChild(c));for(var c="transparent numZoomLevels units isBaseLayer opacity displayInLayerSwitcher singleTile".split(" "),e=0,f=c.length;e<f;++e)(d=this.createOLPropertyNode(a,c[e]))&&b.appendChild(d);return b},createOLPropertyNode:function(a,b){var c=null;null!=a[b]&&(c=this.createElementNS(this.namespaces.ol,"ol:"+b),c.appendChild(this.createTextNode(a[b].toString())));
2555 return c},write_wmc_Server:function(a){a=a.server;var b=this.createElementDefaultNS("Server"),c={service:"OGC:WMS",version:a.version};a.title&&(c.title=a.title);this.setAttributes(b,c);b.appendChild(this.write_wmc_OnlineResource(a.url));return b},write_wmc_URLType:function(a,b,c){a=this.createElementDefaultNS(a);a.appendChild(this.write_wmc_OnlineResource(b));if(c){b=["width","height","format"];for(var d=0;d<b.length;d++)b[d]in c&&a.setAttribute(b[d],c[b[d]])}return a},write_wmc_DimensionList:function(a){var b=
2556 this.createElementDefaultNS("DimensionList"),c;for(c in a.dimensions){var d={},e=a.dimensions[c],f;for(f in e)d[f]="boolean"==typeof e[f]?Number(e[f]):e[f];e="";d.values&&(e=d.values.join(","),delete d.values);b.appendChild(this.createElementDefaultNS("Dimension",e,d))}return b},write_wmc_FormatList:function(a){for(var b=this.createElementDefaultNS("FormatList"),c=0,d=a.formats.length;c<d;c++){var e=a.formats[c];b.appendChild(this.createElementDefaultNS("Format",e.value,e.current&&!0==e.current?{current:"1"}:
2557 null))}return b},write_wmc_StyleList:function(a){var b=this.createElementDefaultNS("StyleList");if((a=a.styles)&&OpenLayers.Util.isArray(a))for(var c,d=0,e=a.length;d<e;d++){var f=a[d],g=this.createElementDefaultNS("Style",null,f.current&&!0==f.current?{current:"1"}:null);f.href?(c=this.createElementDefaultNS("SLD"),f.name&&c.appendChild(this.createElementDefaultNS("Name",f.name)),f.title&&c.appendChild(this.createElementDefaultNS("Title",f.title)),f.legend&&c.appendChild(this.write_wmc_URLType("LegendURL",
2558 f.legend.href,f.legend)),f=this.write_wmc_OnlineResource(f.href),c.appendChild(f),g.appendChild(c)):f.body?(c=this.createElementDefaultNS("SLD"),f.name&&c.appendChild(this.createElementDefaultNS("Name",f.name)),f.title&&c.appendChild(this.createElementDefaultNS("Title",f.title)),f.legend&&c.appendChild(this.write_wmc_URLType("LegendURL",f.legend.href,f.legend)),f=OpenLayers.Format.XML.prototype.read.apply(this,[f.body]).documentElement,c.ownerDocument&&c.ownerDocument.importNode&&(f=c.ownerDocument.importNode(f,
2559 !0)),c.appendChild(f),g.appendChild(c)):(g.appendChild(this.createElementDefaultNS("Name",f.name)),g.appendChild(this.createElementDefaultNS("Title",f.title)),f["abstract"]&&g.appendChild(this.createElementDefaultNS("Abstract",f["abstract"])),f.legend&&g.appendChild(this.write_wmc_URLType("LegendURL",f.legend.href,f.legend)));b.appendChild(g)}return b},write_wmc_OnlineResource:function(a){var b=this.createElementDefaultNS("OnlineResource");this.setAttributeNS(b,this.namespaces.xlink,"xlink:type",
2560 "simple");this.setAttributeNS(b,this.namespaces.xlink,"xlink:href",a);return b},getOnlineResource_href:function(a){var b={};a=a.getElementsByTagName("OnlineResource");0<a.length&&this.read_wmc_OnlineResource(b,a[0]);return b.href},CLASS_NAME:"OpenLayers.Format.WMC.v1"});OpenLayers.Control.PanPanel=OpenLayers.Class(OpenLayers.Control.Panel,{slideFactor:50,slideRatio:null,initialize:function(a){OpenLayers.Control.Panel.prototype.initialize.apply(this,[a]);a={slideFactor:this.slideFactor,slideRatio:this.slideRatio};this.addControls([new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH,a),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH,a),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST,a),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST,a)])},
2561 CLASS_NAME:"OpenLayers.Control.PanPanel"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",template:"${layers}",destroy:function(){this.map.events.un({removelayer:this.updateAttribution,addlayer:this.updateAttribution,changelayer:this.updateAttribution,changebaselayer:this.updateAttribution,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments)},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.map.events.on({changebaselayer:this.updateAttribution,changelayer:this.updateAttribution,
2562 addlayer:this.updateAttribution,removelayer:this.updateAttribution,scope:this});this.updateAttribution();return this.div},updateAttribution:function(){var a=[];if(this.map&&this.map.layers){for(var b=0,c=this.map.layers.length;b<c;b++){var d=this.map.layers[b];d.attribution&&d.getVisibility()&&-1===OpenLayers.Util.indexOf(a,d.attribution)&&a.push(d.attribution)}this.div.innerHTML=OpenLayers.String.format(this.template,{layers:a.join(this.separator)})}},CLASS_NAME:"OpenLayers.Control.Attribution"});OpenLayers.Kinetic=OpenLayers.Class({threshold:0,deceleration:0.0035,nbPoints:100,delay:200,points:void 0,timerId:void 0,initialize:function(a){OpenLayers.Util.extend(this,a)},begin:function(){OpenLayers.Animation.stop(this.timerId);this.timerId=void 0;this.points=[]},update:function(a){this.points.unshift({xy:a,tick:(new Date).getTime()});this.points.length>this.nbPoints&&this.points.pop()},end:function(a){for(var b,c=(new Date).getTime(),d=0,e=this.points.length,f;d<e;d++){f=this.points[d];if(c-
2563 f.tick>this.delay)break;b=f}if(b&&(d=(new Date).getTime()-b.tick,c=Math.sqrt(Math.pow(a.x-b.xy.x,2)+Math.pow(a.y-b.xy.y,2)),d=c/d,!(0==d||d<this.threshold)))return c=Math.asin((a.y-b.xy.y)/c),b.xy.x<=a.x&&(c=Math.PI-c),{speed:d,theta:c}},move:function(a,b){var c=a.speed,d=Math.cos(a.theta),e=-Math.sin(a.theta),f=(new Date).getTime(),g=0,h=0;this.timerId=OpenLayers.Animation.start(OpenLayers.Function.bind(function(){if(null!=this.timerId){var a=(new Date).getTime()-f,l=-this.deceleration*Math.pow(a,
2564 2)/2+c*a,m=l*d,l=l*e,n,p;n=!1;0>=-this.deceleration*a+c&&(OpenLayers.Animation.stop(this.timerId),this.timerId=null,n=!0);a=m-g;p=l-h;g=m;h=l;b(a,p,n)}},this))},CLASS_NAME:"OpenLayers.Kinetic"});OpenLayers.Format.WPSExecute=OpenLayers.Class(OpenLayers.Format.XML,OpenLayers.Format.Filter.v1_1_0,{namespaces:{ows:"http://www.opengis.net/ows/1.1",gml:"http://www.opengis.net/gml",wps:"http://www.opengis.net/wps/1.0.0",wfs:"http://www.opengis.net/wfs",ogc:"http://www.opengis.net/ogc",wcs:"http://www.opengis.net/wcs",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},VERSION:"1.0.0",
2565 schemaLocation:"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",schemaLocationAttr:function(a){},write:function(a){var b;window.ActiveXObject?this.xmldom=b=new ActiveXObject("Microsoft.XMLDOM"):b=document.implementation.createDocument("","",null);a=this.writeNode("wps:Execute",a,b);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},read:function(a){"string"==typeof a&&(a=
2566 OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},writers:{wps:{Execute:function(a){var b=this.createElementNSPlus("wps:Execute",{attributes:{version:this.VERSION,service:"WPS"}});this.writeNode("ows:Identifier",a.identifier,b);this.writeNode("wps:DataInputs",a.dataInputs,b);this.writeNode("wps:ResponseForm",a.responseForm,b);return b},ResponseForm:function(a){var b=this.createElementNSPlus("wps:ResponseForm",{});a.rawDataOutput&&
2567 this.writeNode("wps:RawDataOutput",a.rawDataOutput,b);a.responseDocument&&this.writeNode("wps:ResponseDocument",a.responseDocument,b);return b},ResponseDocument:function(a){var b=this.createElementNSPlus("wps:ResponseDocument",{attributes:{storeExecuteResponse:a.storeExecuteResponse,lineage:a.lineage,status:a.status}});if(a.outputs)for(var c=0,d=a.outputs.length;c<d;c++)this.writeNode("wps:Output",a.outputs[c],b);return b},Output:function(a){var b=this.createElementNSPlus("wps:Output",{attributes:{asReference:a.asReference,
2568 mimeType:a.mimeType,encoding:a.encoding,schema:a.schema}});this.writeNode("ows:Identifier",a.identifier,b);this.writeNode("ows:Title",a.title,b);this.writeNode("ows:Abstract",a["abstract"],b);return b},RawDataOutput:function(a){var b=this.createElementNSPlus("wps:RawDataOutput",{attributes:{mimeType:a.mimeType,encoding:a.encoding,schema:a.schema}});this.writeNode("ows:Identifier",a.identifier,b);return b},DataInputs:function(a){for(var b=this.createElementNSPlus("wps:DataInputs",{}),c=0,d=a.length;c<
2569 d;++c)this.writeNode("wps:Input",a[c],b);return b},Input:function(a){var b=this.createElementNSPlus("wps:Input",{});this.writeNode("ows:Identifier",a.identifier,b);a.title&&this.writeNode("ows:Title",a.title,b);a.data&&this.writeNode("wps:Data",a.data,b);a.reference&&this.writeNode("wps:Reference",a.reference,b);a.boundingBoxData&&this.writeNode("wps:BoundingBoxData",a.boundingBoxData,b);return b},Data:function(a){var b=this.createElementNSPlus("wps:Data",{});a.literalData?this.writeNode("wps:LiteralData",
2570 a.literalData,b):a.complexData?this.writeNode("wps:ComplexData",a.complexData,b):a.boundingBoxData&&this.writeNode("ows:BoundingBox",a.boundingBoxData,b);return b},LiteralData:function(a){return this.createElementNSPlus("wps:LiteralData",{attributes:{uom:a.uom},value:a.value})},ComplexData:function(a){var b=this.createElementNSPlus("wps:ComplexData",{attributes:{mimeType:a.mimeType,encoding:a.encoding,schema:a.schema}}),c=a.value;"string"===typeof c?b.appendChild(this.getXMLDoc().createCDATASection(a.value)):
2571 b.appendChild(c);return b},Reference:function(a){var b=this.createElementNSPlus("wps:Reference",{attributes:{mimeType:a.mimeType,"xlink:href":a.href,method:a.method,encoding:a.encoding,schema:a.schema}});a.body&&this.writeNode("wps:Body",a.body,b);return b},BoundingBoxData:function(a,b){this.writers.ows.BoundingBox.apply(this,[a,b,"wps:BoundingBoxData"])},Body:function(a){var b=this.createElementNSPlus("wps:Body",{});a.wcs?this.writeNode("wcs:GetCoverage",a.wcs,b):a.wfs?(this.featureType=a.wfs.featureType,
2572 this.version=a.wfs.version,this.writeNode("wfs:GetFeature",a.wfs,b)):this.writeNode("wps:Execute",a,b);return b}},wcs:OpenLayers.Format.WCSGetCoverage.prototype.writers.wcs,wfs:OpenLayers.Format.WFST.v1_1_0.prototype.writers.wfs,ogc:OpenLayers.Format.Filter.v1_1_0.prototype.writers.ogc,ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows},readers:{wps:{ExecuteResponse:function(a,b){b.executeResponse={lang:a.getAttribute("lang"),statusLocation:a.getAttribute("statusLocation"),serviceInstance:a.getAttribute("serviceInstance"),
2573 service:a.getAttribute("service")};this.readChildNodes(a,b.executeResponse)},Process:function(a,b){b.process={};this.readChildNodes(a,b.process)},Status:function(a,b){b.status={creationTime:a.getAttribute("creationTime")};this.readChildNodes(a,b.status)},ProcessSucceeded:function(a,b){b.processSucceeded=!0},ProcessOutputs:function(a,b){b.processOutputs=[];this.readChildNodes(a,b.processOutputs)},Output:function(a,b){var c={};this.readChildNodes(a,c);b.push(c)},Reference:function(a,b){b.reference=
2574 {href:a.getAttribute("href"),mimeType:a.getAttribute("mimeType"),encoding:a.getAttribute("encoding"),schema:a.getAttribute("schema")}},Data:function(a,b){b.data={};this.readChildNodes(a,b)},LiteralData:function(a,b){b.literalData={dataType:a.getAttribute("dataType"),uom:a.getAttribute("uom"),value:this.getChildValue(a)}},ComplexData:function(a,b){b.complexData={mimeType:a.getAttribute("mimeType"),schema:a.getAttribute("schema"),encoding:a.getAttribute("encoding"),value:""};if(this.isSimpleContent(a)){var c;
2575 for(c=a.firstChild;c;c=c.nextSibling)switch(c.nodeType){case 3:case 4:b.complexData.value+=c.nodeValue}}else for(c=a.firstChild;c;c=c.nextSibling)1==c.nodeType&&(b.complexData.value=c)},BoundingBox:function(a,b){b.boundingBoxData={dimensions:a.getAttribute("dimensions"),crs:a.getAttribute("crs")};this.readChildNodes(a,b.boundingBoxData)}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WPSExecute"});OpenLayers.Layer.GeoRSS=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,icon:null,popupSize:null,useFeedTitle:!0,initialize:function(a,b,c){OpenLayers.Layer.Markers.prototype.initialize.apply(this,[a,c]);this.location=b;this.features=[]},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null},loadRSS:function(){this.loaded||(this.events.triggerEvent("loadstart"),OpenLayers.Request.GET({url:this.location,
2576 success:this.parseData,scope:this}),this.loaded=!0)},moveTo:function(a,b,c){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);this.visibility&&!this.loaded&&this.loadRSS()},parseData:function(a){var b=a.responseXML;b&&b.documentElement||(b=OpenLayers.Format.XML.prototype.read(a.responseText));if(this.useFeedTitle){a=null;try{a=b.getElementsByTagNameNS("*","title")[0].firstChild.nodeValue}catch(c){a=b.getElementsByTagName("title")[0].firstChild.nodeValue}a&&this.setName(a)}a={};OpenLayers.Util.extend(a,
2577 this.formatOptions);this.map&&!this.projection.equals(this.map.getProjectionObject())&&(a.externalProjection=this.projection,a.internalProjection=this.map.getProjectionObject());b=(new OpenLayers.Format.GeoRSS(a)).read(b);a=0;for(var d=b.length;a<d;a++){var e={},f=b[a];if(f.geometry){var g=f.attributes.title?f.attributes.title:"Untitled",h=f.attributes.description?f.attributes.description:"No description.",k=f.attributes.link?f.attributes.link:"",f=f.geometry.getBounds().getCenterLonLat();e.icon=
2578 null==this.icon?OpenLayers.Marker.defaultIcon():this.icon.clone();e.popupSize=this.popupSize?this.popupSize.clone():new OpenLayers.Size(250,120);if(g||h){e.title=g;e.description=h;var l='<div class="olLayerGeoRSSClose">[x]</div>',l=l+'<div class="olLayerGeoRSSTitle">';k&&(l+='<a class="link" href="'+k+'" target="_blank">');l+=g;k&&(l+="</a>");l+="</div>";l+='<div style="" class="olLayerGeoRSSDescription">';l+=h;l+="</div>";e.popupContentHTML=l}f=new OpenLayers.Feature(this,f,e);this.features.push(f);
2579 e=f.createMarker();e.events.register("click",f,this.markerClick);this.addMarker(e)}}this.events.triggerEvent("loadend")},markerClick:function(a){var b=this==this.layer.selectedFeature;this.layer.selectedFeature=b?null:this;for(var c=0,d=this.layer.map.popups.length;c<d;c++)this.layer.map.removePopup(this.layer.map.popups[c]);b||(b=this.createPopup(),OpenLayers.Event.observe(b.div,"click",OpenLayers.Function.bind(function(){for(var a=0,b=this.layer.map.popups.length;a<b;a++)this.layer.map.removePopup(this.layer.map.popups[a])},
2580 this)),this.layer.map.addPopup(b));OpenLayers.Event.stop(a)},clearFeatures:function(){if(null!=this.features)for(;0<this.features.length;){var a=this.features[0];OpenLayers.Util.removeItem(this.features,a);a.destroy()}},CLASS_NAME:"OpenLayers.Layer.GeoRSS"});OpenLayers.Symbolizer.Point=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Point"});OpenLayers.Symbolizer.Line=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Line"});OpenLayers.Symbolizer.Text=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Text"});OpenLayers.Format.SLD.v1=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,{namespaces:{sld:"http://www.opengis.net/sld",ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"sld",schemaLocation:null,multipleSymbolizers:!1,featureTypeCounter:null,defaultSymbolizer:{fillColor:"#808080",fillOpacity:1,strokeColor:"#000000",strokeOpacity:1,strokeWidth:1,strokeDashstyle:"solid",pointRadius:3,
2581 graphicName:"square"},read:function(a,b){b=OpenLayers.Util.applyDefaults(b,this.options);var c={namedLayers:!0===b.namedLayersAsArray?[]:{}};this.readChildNodes(a,c);return c},readers:OpenLayers.Util.applyDefaults({sld:{StyledLayerDescriptor:function(a,b){b.version=a.getAttribute("version");this.readChildNodes(a,b)},Name:function(a,b){b.name=this.getChildValue(a)},Title:function(a,b){b.title=this.getChildValue(a)},Abstract:function(a,b){b.description=this.getChildValue(a)},NamedLayer:function(a,b){var c=
2582 {userStyles:[],namedStyles:[]};this.readChildNodes(a,c);for(var d=0,e=c.userStyles.length;d<e;++d)c.userStyles[d].layerName=c.name;OpenLayers.Util.isArray(b.namedLayers)?b.namedLayers.push(c):b.namedLayers[c.name]=c},NamedStyle:function(a,b){b.namedStyles.push(this.getChildName(a.firstChild))},UserStyle:function(a,b){var c={defaultsPerSymbolizer:!0,rules:[]};this.featureTypeCounter=-1;this.readChildNodes(a,c);this.multipleSymbolizers?(delete c.defaultsPerSymbolizer,c=new OpenLayers.Style2(c)):c=new OpenLayers.Style(this.defaultSymbolizer,
2583 c);b.userStyles.push(c)},IsDefault:function(a,b){"1"==this.getChildValue(a)&&(b.isDefault=!0)},FeatureTypeStyle:function(a,b){++this.featureTypeCounter;var c={rules:this.multipleSymbolizers?b.rules:[]};this.readChildNodes(a,c);this.multipleSymbolizers||(b.rules=c.rules)},Rule:function(a,b){var c;this.multipleSymbolizers&&(c={symbolizers:[]});c=new OpenLayers.Rule(c);this.readChildNodes(a,c);b.rules.push(c)},ElseFilter:function(a,b){b.elseFilter=!0},MinScaleDenominator:function(a,b){b.minScaleDenominator=
2584 parseFloat(this.getChildValue(a))},MaxScaleDenominator:function(a,b){b.maxScaleDenominator=parseFloat(this.getChildValue(a))},TextSymbolizer:function(a,b){var c={};this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Text(c))):b.symbolizer.Text=OpenLayers.Util.applyDefaults(c,b.symbolizer.Text)},LabelPlacement:function(a,b){this.readChildNodes(a,b)},PointPlacement:function(a,b){var c={};this.readChildNodes(a,c);c.labelRotation=
2585 c.rotation;delete c.rotation;var d,e=b.labelAnchorPointX,f=b.labelAnchorPointY;e<=1/3?d="l":e>1/3&&e<2/3?d="c":e>=2/3&&(d="r");f<=1/3?d+="b":f>1/3&&f<2/3?d+="m":f>=2/3&&(d+="t");c.labelAlign=d;OpenLayers.Util.applyDefaults(b,c)},AnchorPoint:function(a,b){this.readChildNodes(a,b)},AnchorPointX:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelAnchorPointX=c)},AnchorPointY:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelAnchorPointY=c)},Displacement:function(a,
2586 b){this.readChildNodes(a,b)},DisplacementX:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelXOffset=c)},DisplacementY:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelYOffset=c)},LinePlacement:function(a,b){this.readChildNodes(a,b)},PerpendicularOffset:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelPerpendicularOffset=c)},Label:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.label=c)},Font:function(a,b){this.readChildNodes(a,
2587 b)},Halo:function(a,b){var c={};this.readChildNodes(a,c);b.haloRadius=c.haloRadius;b.haloColor=c.fillColor;b.haloOpacity=c.fillOpacity},Radius:function(a,b){var c=this.readers.ogc._expression.call(this,a);null!=c&&(b.haloRadius=c)},RasterSymbolizer:function(a,b){var c={};this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Raster(c))):b.symbolizer.Raster=OpenLayers.Util.applyDefaults(c,b.symbolizer.Raster)},Geometry:function(a,
2588 b){b.geometry={};this.readChildNodes(a,b.geometry)},ColorMap:function(a,b){b.colorMap=[];this.readChildNodes(a,b.colorMap)},ColorMapEntry:function(a,b){var c=a.getAttribute("quantity"),d=a.getAttribute("opacity");b.push({color:a.getAttribute("color"),quantity:null!==c?parseFloat(c):void 0,label:a.getAttribute("label")||void 0,opacity:null!==d?parseFloat(d):void 0})},LineSymbolizer:function(a,b){var c={};this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Line(c))):
2589 b.symbolizer.Line=OpenLayers.Util.applyDefaults(c,b.symbolizer.Line)},PolygonSymbolizer:function(a,b){var c={fill:!1,stroke:!1};this.multipleSymbolizers||(c=b.symbolizer.Polygon||c);this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Polygon(c))):b.symbolizer.Polygon=c},PointSymbolizer:function(a,b){var c={fill:!1,stroke:!1,graphic:!1};this.multipleSymbolizers||(c=b.symbolizer.Point||c);this.readChildNodes(a,c);this.multipleSymbolizers?
2590 (c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Point(c))):b.symbolizer.Point=c},Stroke:function(a,b){b.stroke=!0;this.readChildNodes(a,b)},Fill:function(a,b){b.fill=!0;this.readChildNodes(a,b)},CssParameter:function(a,b){var c=a.getAttribute("name"),d=this.cssMap[c];b.label&&("fill"===c?d="fontColor":"fill-opacity"===c&&(d="fontOpacity"));d&&(c=this.readers.ogc._expression.call(this,a))&&(b[d]=c)},Graphic:function(a,b){b.graphic=!0;var c={};this.readChildNodes(a,c);
2591 for(var d="stroke strokeColor strokeWidth strokeOpacity strokeLinecap fill fillColor fillOpacity graphicName rotation graphicFormat".split(" "),e,f,g=0,h=d.length;g<h;++g)e=d[g],f=c[e],void 0!=f&&(b[e]=f);void 0!=c.opacity&&(b.graphicOpacity=c.opacity);void 0!=c.size&&(isNaN(c.size/2)?b.graphicWidth=c.size:b.pointRadius=c.size/2);void 0!=c.href&&(b.externalGraphic=c.href);void 0!=c.rotation&&(b.rotation=c.rotation)},ExternalGraphic:function(a,b){this.readChildNodes(a,b)},Mark:function(a,b){this.readChildNodes(a,
2592 b)},WellKnownName:function(a,b){b.graphicName=this.getChildValue(a)},Opacity:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.opacity=c)},Size:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.size=c)},Rotation:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.rotation=c)},OnlineResource:function(a,b){b.href=this.getAttributeNS(a,this.namespaces.xlink,"href")},Format:function(a,b){b.graphicFormat=this.getChildValue(a)}}},OpenLayers.Format.Filter.v1_0_0.prototype.readers),
2593 cssMap:{stroke:"strokeColor","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-dasharray":"strokeDashstyle",fill:"fillColor","fill-opacity":"fillOpacity","font-family":"fontFamily","font-size":"fontSize","font-weight":"fontWeight","font-style":"fontStyle"},getCssProperty:function(a){var b=null,c;for(c in this.cssMap)if(this.cssMap[c]==a){b=c;break}return b},getGraphicFormat:function(a){var b,c;for(c in this.graphicFormats)if(this.graphicFormats[c].test(a)){b=
2594 c;break}return b||this.defaultGraphicFormat},defaultGraphicFormat:"image/png",graphicFormats:{"image/jpeg":/\.jpe?g$/i,"image/gif":/\.gif$/i,"image/png":/\.png$/i},write:function(a){return this.writers.sld.StyledLayerDescriptor.apply(this,[a])},writers:OpenLayers.Util.applyDefaults({sld:{_OGCExpression:function(a,b){var c=this.createElementNSPlus(a),d="string"==typeof b?b.split("${"):[b];c.appendChild(this.createTextNode(d[0]));for(var e,f,g=1,h=d.length;g<h;g++)e=d[g],f=e.indexOf("}"),0<f?(this.writeNode("ogc:PropertyName",
2595 {property:e.substring(0,f)},c),c.appendChild(this.createTextNode(e.substring(++f)))):c.appendChild(this.createTextNode("${"+e));return c},StyledLayerDescriptor:function(a){var b=this.createElementNSPlus("sld:StyledLayerDescriptor",{attributes:{version:this.VERSION,"xsi:schemaLocation":this.schemaLocation}});b.setAttribute("xmlns:ogc",this.namespaces.ogc);b.setAttribute("xmlns:gml",this.namespaces.gml);a.name&&this.writeNode("Name",a.name,b);a.title&&this.writeNode("Title",a.title,b);a.description&&
2596 this.writeNode("Abstract",a.description,b);if(OpenLayers.Util.isArray(a.namedLayers))for(var c=0,d=a.namedLayers.length;c<d;++c)this.writeNode("NamedLayer",a.namedLayers[c],b);else for(c in a.namedLayers)this.writeNode("NamedLayer",a.namedLayers[c],b);return b},Name:function(a){return this.createElementNSPlus("sld:Name",{value:a})},Title:function(a){return this.createElementNSPlus("sld:Title",{value:a})},Abstract:function(a){return this.createElementNSPlus("sld:Abstract",{value:a})},NamedLayer:function(a){var b=
2597 this.createElementNSPlus("sld:NamedLayer");this.writeNode("Name",a.name,b);if(a.namedStyles)for(var c=0,d=a.namedStyles.length;c<d;++c)this.writeNode("NamedStyle",a.namedStyles[c],b);if(a.userStyles)for(c=0,d=a.userStyles.length;c<d;++c)this.writeNode("UserStyle",a.userStyles[c],b);return b},NamedStyle:function(a){var b=this.createElementNSPlus("sld:NamedStyle");this.writeNode("Name",a,b);return b},UserStyle:function(a){var b=this.createElementNSPlus("sld:UserStyle");a.name&&this.writeNode("Name",
2598 a.name,b);a.title&&this.writeNode("Title",a.title,b);a.description&&this.writeNode("Abstract",a.description,b);a.isDefault&&this.writeNode("IsDefault",a.isDefault,b);if(this.multipleSymbolizers&&a.rules){for(var c={0:[]},d=[0],e,f,g,h,k,l=0,m=a.rules.length;l<m;++l)if(e=a.rules[l],e.symbolizers){f={};for(var n=0,p=e.symbolizers.length;n<p;++n)g=e.symbolizers[n],h=g.zIndex,h in f||(k=e.clone(),k.symbolizers=[],f[h]=k),f[h].symbolizers.push(g.clone());for(h in f)h in c||(d.push(h),c[h]=[]),c[h].push(f[h])}else c[0].push(e.clone());
2599 d.sort();l=0;for(m=d.length;l<m;++l)e=c[d[l]],0<e.length&&(k=a.clone(),k.rules=c[d[l]],this.writeNode("FeatureTypeStyle",k,b))}else this.writeNode("FeatureTypeStyle",a,b);return b},IsDefault:function(a){return this.createElementNSPlus("sld:IsDefault",{value:a?"1":"0"})},FeatureTypeStyle:function(a){for(var b=this.createElementNSPlus("sld:FeatureTypeStyle"),c=0,d=a.rules.length;c<d;++c)this.writeNode("Rule",a.rules[c],b);return b},Rule:function(a){var b=this.createElementNSPlus("sld:Rule");a.name&&
2600 this.writeNode("Name",a.name,b);a.title&&this.writeNode("Title",a.title,b);a.description&&this.writeNode("Abstract",a.description,b);a.elseFilter?this.writeNode("ElseFilter",null,b):a.filter&&this.writeNode("ogc:Filter",a.filter,b);void 0!=a.minScaleDenominator&&this.writeNode("MinScaleDenominator",a.minScaleDenominator,b);void 0!=a.maxScaleDenominator&&this.writeNode("MaxScaleDenominator",a.maxScaleDenominator,b);var c,d;if(this.multipleSymbolizers&&a.symbolizers)for(var e=0,f=a.symbolizers.length;e<
2601 f;++e)d=a.symbolizers[e],c=d.CLASS_NAME.split(".").pop(),this.writeNode(c+"Symbolizer",d,b);else for(var f=OpenLayers.Style.SYMBOLIZER_PREFIXES,e=0,g=f.length;e<g;++e)c=f[e],(d=a.symbolizer[c])&&this.writeNode(c+"Symbolizer",d,b);return b},ElseFilter:function(){return this.createElementNSPlus("sld:ElseFilter")},MinScaleDenominator:function(a){return this.createElementNSPlus("sld:MinScaleDenominator",{value:a})},MaxScaleDenominator:function(a){return this.createElementNSPlus("sld:MaxScaleDenominator",
2602 {value:a})},LineSymbolizer:function(a){var b=this.createElementNSPlus("sld:LineSymbolizer");this.writeNode("Stroke",a,b);return b},Stroke:function(a){var b=this.createElementNSPlus("sld:Stroke");void 0!=a.strokeColor&&this.writeNode("CssParameter",{symbolizer:a,key:"strokeColor"},b);void 0!=a.strokeOpacity&&this.writeNode("CssParameter",{symbolizer:a,key:"strokeOpacity"},b);void 0!=a.strokeWidth&&this.writeNode("CssParameter",{symbolizer:a,key:"strokeWidth"},b);void 0!=a.strokeDashstyle&&"solid"!==
2603 a.strokeDashstyle&&this.writeNode("CssParameter",{symbolizer:a,key:"strokeDashstyle"},b);void 0!=a.strokeLinecap&&this.writeNode("CssParameter",{symbolizer:a,key:"strokeLinecap"},b);return b},CssParameter:function(a){return this.createElementNSPlus("sld:CssParameter",{attributes:{name:this.getCssProperty(a.key)},value:a.symbolizer[a.key]})},TextSymbolizer:function(a){var b=this.createElementNSPlus("sld:TextSymbolizer");null!=a.label&&this.writeNode("Label",a.label,b);null==a.fontFamily&&null==a.fontSize&&
2604 null==a.fontWeight&&null==a.fontStyle||this.writeNode("Font",a,b);null==a.labelAnchorPointX&&null==a.labelAnchorPointY&&null==a.labelAlign&&null==a.labelXOffset&&null==a.labelYOffset&&null==a.labelRotation&&null==a.labelPerpendicularOffset||this.writeNode("LabelPlacement",a,b);null==a.haloRadius&&null==a.haloColor&&null==a.haloOpacity||this.writeNode("Halo",a,b);null==a.fontColor&&null==a.fontOpacity||this.writeNode("Fill",{fillColor:a.fontColor,fillOpacity:a.fontOpacity},b);return b},LabelPlacement:function(a){var b=
2605 this.createElementNSPlus("sld:LabelPlacement");null==a.labelAnchorPointX&&null==a.labelAnchorPointY&&null==a.labelAlign&&null==a.labelXOffset&&null==a.labelYOffset&&null==a.labelRotation||null!=a.labelPerpendicularOffset||this.writeNode("PointPlacement",a,b);null!=a.labelPerpendicularOffset&&this.writeNode("LinePlacement",a,b);return b},LinePlacement:function(a){var b=this.createElementNSPlus("sld:LinePlacement");this.writeNode("PerpendicularOffset",a.labelPerpendicularOffset,b);return b},PerpendicularOffset:function(a){return this.createElementNSPlus("sld:PerpendicularOffset",
2606 {value:a})},PointPlacement:function(a){var b=this.createElementNSPlus("sld:PointPlacement");null==a.labelAnchorPointX&&null==a.labelAnchorPointY&&null==a.labelAlign||this.writeNode("AnchorPoint",a,b);null==a.labelXOffset&&null==a.labelYOffset||this.writeNode("Displacement",a,b);null!=a.labelRotation&&this.writeNode("Rotation",a.labelRotation,b);return b},AnchorPoint:function(a){var b=this.createElementNSPlus("sld:AnchorPoint"),c=a.labelAnchorPointX,d=a.labelAnchorPointY;null!=c&&this.writeNode("AnchorPointX",
2607 c,b);null!=d&&this.writeNode("AnchorPointY",d,b);if(null==c&&null==d){var e=a.labelAlign.substr(0,1);a=a.labelAlign.substr(1,1);"l"===e?c=0:"c"===e?c=0.5:"r"===e&&(c=1);"b"===a?d=0:"m"===a?d=0.5:"t"===a&&(d=1);this.writeNode("AnchorPointX",c,b);this.writeNode("AnchorPointY",d,b)}return b},AnchorPointX:function(a){return this.createElementNSPlus("sld:AnchorPointX",{value:a})},AnchorPointY:function(a){return this.createElementNSPlus("sld:AnchorPointY",{value:a})},Displacement:function(a){var b=this.createElementNSPlus("sld:Displacement");
2608 null!=a.labelXOffset&&this.writeNode("DisplacementX",a.labelXOffset,b);null!=a.labelYOffset&&this.writeNode("DisplacementY",a.labelYOffset,b);return b},DisplacementX:function(a){return this.createElementNSPlus("sld:DisplacementX",{value:a})},DisplacementY:function(a){return this.createElementNSPlus("sld:DisplacementY",{value:a})},Font:function(a){var b=this.createElementNSPlus("sld:Font");a.fontFamily&&this.writeNode("CssParameter",{symbolizer:a,key:"fontFamily"},b);a.fontSize&&this.writeNode("CssParameter",
2609 {symbolizer:a,key:"fontSize"},b);a.fontWeight&&this.writeNode("CssParameter",{symbolizer:a,key:"fontWeight"},b);a.fontStyle&&this.writeNode("CssParameter",{symbolizer:a,key:"fontStyle"},b);return b},Label:function(a){return this.writers.sld._OGCExpression.call(this,"sld:Label",a)},Halo:function(a){var b=this.createElementNSPlus("sld:Halo");a.haloRadius&&this.writeNode("Radius",a.haloRadius,b);(a.haloColor||a.haloOpacity)&&this.writeNode("Fill",{fillColor:a.haloColor,fillOpacity:a.haloOpacity},b);
2610 return b},Radius:function(a){return this.createElementNSPlus("sld:Radius",{value:a})},RasterSymbolizer:function(a){var b=this.createElementNSPlus("sld:RasterSymbolizer");a.geometry&&this.writeNode("Geometry",a.geometry,b);a.opacity&&this.writeNode("Opacity",a.opacity,b);a.colorMap&&this.writeNode("ColorMap",a.colorMap,b);return b},Geometry:function(a){var b=this.createElementNSPlus("sld:Geometry");a.property&&this.writeNode("ogc:PropertyName",a,b);return b},ColorMap:function(a){for(var b=this.createElementNSPlus("sld:ColorMap"),
2611 c=0,d=a.length;c<d;++c)this.writeNode("ColorMapEntry",a[c],b);return b},ColorMapEntry:function(a){var b=this.createElementNSPlus("sld:ColorMapEntry");b.setAttribute("color",a.color);void 0!==a.opacity&&b.setAttribute("opacity",parseFloat(a.opacity));void 0!==a.quantity&&b.setAttribute("quantity",parseFloat(a.quantity));void 0!==a.label&&b.setAttribute("label",a.label);return b},PolygonSymbolizer:function(a){var b=this.createElementNSPlus("sld:PolygonSymbolizer");!1!==a.fill&&this.writeNode("Fill",
2612 a,b);!1!==a.stroke&&this.writeNode("Stroke",a,b);return b},Fill:function(a){var b=this.createElementNSPlus("sld:Fill");a.fillColor&&this.writeNode("CssParameter",{symbolizer:a,key:"fillColor"},b);null!=a.fillOpacity&&this.writeNode("CssParameter",{symbolizer:a,key:"fillOpacity"},b);return b},PointSymbolizer:function(a){var b=this.createElementNSPlus("sld:PointSymbolizer");this.writeNode("Graphic",a,b);return b},Graphic:function(a){var b=this.createElementNSPlus("sld:Graphic");void 0!=a.externalGraphic?
2613 this.writeNode("ExternalGraphic",a,b):this.writeNode("Mark",a,b);void 0!=a.graphicOpacity&&this.writeNode("Opacity",a.graphicOpacity,b);void 0!=a.pointRadius?this.writeNode("Size",2*a.pointRadius,b):void 0!=a.graphicWidth&&this.writeNode("Size",a.graphicWidth,b);void 0!=a.rotation&&this.writeNode("Rotation",a.rotation,b);return b},ExternalGraphic:function(a){var b=this.createElementNSPlus("sld:ExternalGraphic");this.writeNode("OnlineResource",a.externalGraphic,b);a=a.graphicFormat||this.getGraphicFormat(a.externalGraphic);
2614 this.writeNode("Format",a,b);return b},Mark:function(a){var b=this.createElementNSPlus("sld:Mark");a.graphicName&&this.writeNode("WellKnownName",a.graphicName,b);!1!==a.fill&&this.writeNode("Fill",a,b);!1!==a.stroke&&this.writeNode("Stroke",a,b);return b},WellKnownName:function(a){return this.createElementNSPlus("sld:WellKnownName",{value:a})},Opacity:function(a){return this.createElementNSPlus("sld:Opacity",{value:a})},Size:function(a){return this.writers.sld._OGCExpression.call(this,"sld:Size",
2615 a)},Rotation:function(a){return this.createElementNSPlus("sld:Rotation",{value:a})},OnlineResource:function(a){return this.createElementNSPlus("sld:OnlineResource",{attributes:{"xlink:type":"simple","xlink:href":a}})},Format:function(a){return this.createElementNSPlus("sld:Format",{value:a})}}},OpenLayers.Format.Filter.v1_0_0.prototype.writers),CLASS_NAME:"OpenLayers.Format.SLD.v1"});OpenLayers.Layer.WMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{service:"WMS",version:"1.1.1",request:"GetMap",styles:"",format:"image/jpeg"},isBaseLayer:!0,encodeBBOX:!1,noMagic:!1,yx:{},initialize:function(a,b,c,d){var e=[];c=OpenLayers.Util.upperCaseObject(c);1.3<=parseFloat(c.VERSION)&&!c.EXCEPTIONS&&(c.EXCEPTIONS="INIMAGE");e.push(a,b,c,d);OpenLayers.Layer.Grid.prototype.initialize.apply(this,e);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));
2616 !this.noMagic&&(this.params.TRANSPARENT&&"true"==this.params.TRANSPARENT.toString().toLowerCase())&&(null!=d&&d.isBaseLayer||(this.isBaseLayer=!1),"image/jpeg"==this.params.FORMAT&&(this.params.FORMAT=OpenLayers.Util.alphaHack()?"image/gif":"image/png"))},clone:function(a){null==a&&(a=new OpenLayers.Layer.WMS(this.name,this.url,this.params,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},reverseAxisOrder:function(){var a=this.projection.getCode();return 1.3<=parseFloat(this.params.VERSION)&&
2617 !!(this.yx[a]||OpenLayers.Projection.defaults[a]&&OpenLayers.Projection.defaults[a].yx)},getURL:function(a){a=this.adjustBounds(a);var b=this.getImageSize(),c={},d=this.reverseAxisOrder();c.BBOX=this.encodeBBOX?a.toBBOX(null,d):a.toArray(d);c.WIDTH=b.w;c.HEIGHT=b.h;return this.getFullRequestString(c)},mergeNewParams:function(a){a=[OpenLayers.Util.upperCaseObject(a)];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,a)},getFullRequestString:function(a,b){var c=this.map.getProjectionObject(),
2618 c=this.projection&&this.projection.equals(c)?this.projection.getCode():c.getCode(),c="none"==c?null:c;1.3<=parseFloat(this.params.VERSION)?this.params.CRS=c:this.params.SRS=c;"boolean"==typeof this.params.TRANSPARENT&&(a.TRANSPARENT=this.params.TRANSPARENT?"TRUE":"FALSE");return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments)},CLASS_NAME:"OpenLayers.Layer.WMS"});OpenLayers.Layer.KaMap=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,DEFAULT_PARAMS:{i:"jpeg",map:""},initialize:function(a,b,c,d){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS)},getURL:function(a){a=this.adjustBounds(a);var b=this.map.getResolution(),c=Math.round(1E4*this.map.getScale())/1E4,d=Math.round(a.left/b);a=-Math.round(a.top/b);return this.getFullRequestString({t:a,l:d,s:c})},calculateGridLayout:function(a,
2619 b,c){b=c*this.tileSize.w;c*=this.tileSize.h;return{tilelon:b,tilelat:c,startcol:Math.floor(a.left/b)-this.buffer,startrow:Math.floor(a.top/c)+this.buffer}},getTileBoundsForGridIndex:function(a,b){this.getTileOrigin();var c=this.gridLayout,d=c.tilelon,e=c.tilelat,f=(c.startcol+b)*d,c=(c.startrow-a)*e;return new OpenLayers.Bounds(f,c,f+d,c+e)},clone:function(a){null==a&&(a=new OpenLayers.Layer.KaMap(this.name,this.url,this.params,this.getOptions()));a=OpenLayers.Layer.Grid.prototype.clone.apply(this,
2620 [a]);null!=this.tileSize&&(a.tileSize=this.tileSize.clone());a.grid=[];return a},getTileBounds:function(a){var b=this.getResolution(),c=b*this.tileSize.w,b=b*this.tileSize.h,d=this.getLonLatFromViewPortPx(a);a=c*Math.floor(d.lon/c);d=b*Math.floor(d.lat/b);return new OpenLayers.Bounds(a,d,a+c,d+b)},CLASS_NAME:"OpenLayers.Layer.KaMap"});OpenLayers.Format.WMC.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd",initialize:function(a){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[a])},read_sld_MinScaleDenominator:function(a,b){var c=parseFloat(this.getChildValue(b));0<c&&(a.maxScale=c)},read_sld_MaxScaleDenominator:function(a,b){a.minScale=parseFloat(this.getChildValue(b))},read_wmc_SRS:function(a,b){"srs"in
2621 a||(a.srs={});a.srs[this.getChildValue(b)]=!0},write_wmc_Layer:function(a){var b=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[a]);if(a.maxScale){var c=this.createElementNS(this.namespaces.sld,"sld:MinScaleDenominator");c.appendChild(this.createTextNode(a.maxScale.toPrecision(16)));b.appendChild(c)}a.minScale&&(c=this.createElementNS(this.namespaces.sld,"sld:MaxScaleDenominator"),c.appendChild(this.createTextNode(a.minScale.toPrecision(16))),b.appendChild(c));if(a.srs)for(var d in a.srs)b.appendChild(this.createElementDefaultNS("SRS",
2622 d));b.appendChild(this.write_wmc_FormatList(a));b.appendChild(this.write_wmc_StyleList(a));a.dimensions&&b.appendChild(this.write_wmc_DimensionList(a));b.appendChild(this.write_wmc_LayerExtension(a));return b},CLASS_NAME:"OpenLayers.Format.WMC.v1_1_0"});OpenLayers.Format.XLS=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.1.0",stringifyOutput:!0,CLASS_NAME:"OpenLayers.Format.XLS"});OpenLayers.Format.XLS.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xls:"http://www.opengis.net/xls",gml:"http://www.opengis.net/gml",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},xy:!0,defaultPrefix:"xls",schemaLocation:null,read:function(a,b){OpenLayers.Util.applyDefaults(b,this.options);var c={};this.readChildNodes(a,c);return c},readers:{xls:{XLS:function(a,b){b.version=a.getAttribute("version");
2623 this.readChildNodes(a,b)},Response:function(a,b){this.readChildNodes(a,b)},GeocodeResponse:function(a,b){b.responseLists=[];this.readChildNodes(a,b)},GeocodeResponseList:function(a,b){var c={features:[],numberOfGeocodedAddresses:parseInt(a.getAttribute("numberOfGeocodedAddresses"))};b.responseLists.push(c);this.readChildNodes(a,c)},GeocodedAddress:function(a,b){var c=new OpenLayers.Feature.Vector;b.features.push(c);this.readChildNodes(a,c);c.geometry=c.components[0]},GeocodeMatchCode:function(a,b){b.attributes.matchCode=
2624 {accuracy:parseFloat(a.getAttribute("accuracy")),matchType:a.getAttribute("matchType")}},Address:function(a,b){var c={countryCode:a.getAttribute("countryCode"),addressee:a.getAttribute("addressee"),street:[],place:[]};b.attributes.address=c;this.readChildNodes(a,c)},freeFormAddress:function(a,b){b.freeFormAddress=this.getChildValue(a)},StreetAddress:function(a,b){this.readChildNodes(a,b)},Building:function(a,b){b.building={number:a.getAttribute("number"),subdivision:a.getAttribute("subdivision"),
2625 buildingName:a.getAttribute("buildingName")}},Street:function(a,b){b.street.push(this.getChildValue(a))},Place:function(a,b){b.place[a.getAttribute("type")]=this.getChildValue(a)},PostalCode:function(a,b){b.postalCode=this.getChildValue(a)}},gml:OpenLayers.Format.GML.v3.prototype.readers.gml},write:function(a){return this.writers.xls.XLS.apply(this,[a])},writers:{xls:{XLS:function(a){var b=this.createElementNSPlus("xls:XLS",{attributes:{version:this.VERSION,"xsi:schemaLocation":this.schemaLocation}});
2626 this.writeNode("RequestHeader",a.header,b);this.writeNode("Request",a,b);return b},RequestHeader:function(a){return this.createElementNSPlus("xls:RequestHeader")},Request:function(a){var b=this.createElementNSPlus("xls:Request",{attributes:{methodName:"GeocodeRequest",requestID:a.requestID||"",version:this.VERSION}});this.writeNode("GeocodeRequest",a.addresses,b);return b},GeocodeRequest:function(a){for(var b=this.createElementNSPlus("xls:GeocodeRequest"),c=0,d=a.length;c<d;c++)this.writeNode("Address",
2627 a[c],b);return b},Address:function(a){var b=this.createElementNSPlus("xls:Address",{attributes:{countryCode:a.countryCode}});a.freeFormAddress?this.writeNode("freeFormAddress",a.freeFormAddress,b):(a.street&&this.writeNode("StreetAddress",a,b),a.municipality&&this.writeNode("Municipality",a.municipality,b),a.countrySubdivision&&this.writeNode("CountrySubdivision",a.countrySubdivision,b),a.postalCode&&this.writeNode("PostalCode",a.postalCode,b));return b},freeFormAddress:function(a){return this.createElementNSPlus("freeFormAddress",
2628 {value:a})},StreetAddress:function(a){var b=this.createElementNSPlus("xls:StreetAddress");a.building&&this.writeNode(b,"Building",a.building);a=a.street;OpenLayers.Util.isArray(a)||(a=[a]);for(var c=0,d=a.length;c<d;c++)this.writeNode("Street",a[c],b);return b},Building:function(a){return this.createElementNSPlus("xls:Building",{attributes:{number:a.number,subdivision:a.subdivision,buildingName:a.buildingName}})},Street:function(a){return this.createElementNSPlus("xls:Street",{value:a})},Municipality:function(a){return this.createElementNSPlus("xls:Place",
2629 {attributes:{type:"Municipality"},value:a})},CountrySubdivision:function(a){return this.createElementNSPlus("xls:Place",{attributes:{type:"CountrySubdivision"},value:a})},PostalCode:function(a){return this.createElementNSPlus("xls:PostalCode",{value:a})}}},CLASS_NAME:"OpenLayers.Format.XLS.v1"});OpenLayers.Format.XLS.v1_1_0=OpenLayers.Class(OpenLayers.Format.XLS.v1,{VERSION:"1.1",schemaLocation:"http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd",CLASS_NAME:"OpenLayers.Format.XLS.v1_1_0"});OpenLayers.Format.XLS.v1_1=OpenLayers.Format.XLS.v1_1_0;OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15E3,translationParameters:null,symbolMetrics:null,initialize:function(a){this.supported()&&(OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments),this.translationParameters={x:0,y:0},this.symbolMetrics={})},supported:function(){return document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#SVG",
2630 "1.1")||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"))},inValidRange:function(a,b,c){a+=c?0:this.translationParameters.x;b+=c?0:this.translationParameters.y;return a>=-this.MAX_PIXEL&&a<=this.MAX_PIXEL&&b>=-this.MAX_PIXEL&&b<=this.MAX_PIXEL},setExtent:function(a,b){var c=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments),d=this.getResolution(),e=-a.left/d,d=a.top/d;if(b)return this.left=e,this.top=d,this.rendererRoot.setAttributeNS(null,
2631 "viewBox","0 0 "+this.size.w+" "+this.size.h),this.translate(this.xOffset,0),!0;(e=this.translate(e-this.left+this.xOffset,d-this.top))||this.setExtent(a,!0);return c&&e},translate:function(a,b){if(this.inValidRange(a,b,!0)){var c="";if(a||b)c="translate("+a+","+b+")";this.root.setAttributeNS(null,"transform",c);this.translationParameters={x:a,y:b};return!0}return!1},setSize:function(a){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w);
2632 this.rendererRoot.setAttributeNS(null,"height",this.size.h)},getNodeType:function(a,b){var c=null;switch(a.CLASS_NAME){case "OpenLayers.Geometry.Point":c=b.externalGraphic?"image":this.isComplexSymbol(b.graphicName)?"svg":"circle";break;case "OpenLayers.Geometry.Rectangle":c="rect";break;case "OpenLayers.Geometry.LineString":c="polyline";break;case "OpenLayers.Geometry.LinearRing":c="polygon";break;case "OpenLayers.Geometry.Polygon":case "OpenLayers.Geometry.Curve":c="path"}return c},setStyle:function(a,
2633 b,c){b=b||a._style;c=c||a._options;var d=b.title||b.graphicTitle;if(d){a.setAttributeNS(null,"title",d);var e=a.getElementsByTagName("title");0<e.length?e[0].firstChild.textContent=d:(e=this.nodeFactory(null,"title"),e.textContent=d,a.appendChild(e))}var e=parseFloat(a.getAttributeNS(null,"r")),d=1,f;if("OpenLayers.Geometry.Point"==a._geometryClass&&e){a.style.visibility="";if(!1===b.graphic)a.style.visibility="hidden";else if(b.externalGraphic){f=this.getPosition(a);b.graphicWidth&&b.graphicHeight&&
2634 a.setAttributeNS(null,"preserveAspectRatio","none");var e=b.graphicWidth||b.graphicHeight,g=b.graphicHeight||b.graphicWidth,e=e?e:2*b.pointRadius,g=g?g:2*b.pointRadius,h=void 0!=b.graphicYOffset?b.graphicYOffset:-(0.5*g),k=b.graphicOpacity||b.fillOpacity;a.setAttributeNS(null,"x",(f.x+(void 0!=b.graphicXOffset?b.graphicXOffset:-(0.5*e))).toFixed());a.setAttributeNS(null,"y",(f.y+h).toFixed());a.setAttributeNS(null,"width",e);a.setAttributeNS(null,"height",g);a.setAttributeNS(this.xlinkns,"xlink:href",
2635 b.externalGraphic);a.setAttributeNS(null,"style","opacity: "+k);a.onclick=OpenLayers.Event.preventDefault}else if(this.isComplexSymbol(b.graphicName)){var e=3*b.pointRadius,g=2*e,l=this.importSymbol(b.graphicName);f=this.getPosition(a);d=3*this.symbolMetrics[l.id][0]/g;h=a.parentNode;k=a.nextSibling;h&&h.removeChild(a);a.firstChild&&a.removeChild(a.firstChild);a.appendChild(l.firstChild.cloneNode(!0));a.setAttributeNS(null,"viewBox",l.getAttributeNS(null,"viewBox"));a.setAttributeNS(null,"width",
2636 g);a.setAttributeNS(null,"height",g);a.setAttributeNS(null,"x",f.x-e);a.setAttributeNS(null,"y",f.y-e);k?h.insertBefore(a,k):h&&h.appendChild(a)}else a.setAttributeNS(null,"r",b.pointRadius);e=b.rotation;void 0===e&&void 0===a._rotation||!f||(a._rotation=e,e|=0,"svg"!==a.nodeName?a.setAttributeNS(null,"transform","rotate("+e+" "+f.x+" "+f.y+")"):(f=this.symbolMetrics[l.id],a.firstChild.setAttributeNS(null,"transform","rotate("+e+" "+f[1]+" "+f[2]+")")))}c.isFilled?(a.setAttributeNS(null,"fill",b.fillColor),
2637 a.setAttributeNS(null,"fill-opacity",b.fillOpacity)):a.setAttributeNS(null,"fill","none");c.isStroked?(a.setAttributeNS(null,"stroke",b.strokeColor),a.setAttributeNS(null,"stroke-opacity",b.strokeOpacity),a.setAttributeNS(null,"stroke-width",b.strokeWidth*d),a.setAttributeNS(null,"stroke-linecap",b.strokeLinecap||"round"),a.setAttributeNS(null,"stroke-linejoin","round"),b.strokeDashstyle&&a.setAttributeNS(null,"stroke-dasharray",this.dashStyle(b,d))):a.setAttributeNS(null,"stroke","none");b.pointerEvents&&
2638 a.setAttributeNS(null,"pointer-events",b.pointerEvents);null!=b.cursor&&a.setAttributeNS(null,"cursor",b.cursor);return a},dashStyle:function(a,b){var c=a.strokeWidth*b,d=a.strokeDashstyle;switch(d){case "solid":return"none";case "dot":return[1,4*c].join();case "dash":return[4*c,4*c].join();case "dashdot":return[4*c,4*c,1,4*c].join();case "longdash":return[8*c,4*c].join();case "longdashdot":return[8*c,4*c,1,4*c].join();default:return OpenLayers.String.trim(d).replace(/\s+/g,",")}},createNode:function(a,
2639 b){var c=document.createElementNS(this.xmlns,a);b&&c.setAttributeNS(null,"id",b);return c},nodeTypeCompare:function(a,b){return b==a.nodeName},createRenderRoot:function(){var a=this.nodeFactory(this.container.id+"_svgRoot","svg");a.style.display="block";return a},createRoot:function(a){return this.nodeFactory(this.container.id+a,"g")},createDefs:function(){var a=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(a);return a},drawPoint:function(a,b){return this.drawCircle(a,
2640 b,1)},drawCircle:function(a,b,c){var d=this.getResolution(),e=(b.x-this.featureDx)/d+this.left;b=this.top-b.y/d;return this.inValidRange(e,b)?(a.setAttributeNS(null,"cx",e),a.setAttributeNS(null,"cy",b),a.setAttributeNS(null,"r",c),a):!1},drawLineString:function(a,b){var c=this.getComponentsString(b.components);return c.path?(a.setAttributeNS(null,"points",c.path),c.complete?a:null):!1},drawLinearRing:function(a,b){var c=this.getComponentsString(b.components);return c.path?(a.setAttributeNS(null,
2641 "points",c.path),c.complete?a:null):!1},drawPolygon:function(a,b){for(var c="",d=!0,e=!0,f,g,h=0,k=b.components.length;h<k;h++)c+=" M",f=this.getComponentsString(b.components[h].components," "),(g=f.path)?(c+=" "+g,e=f.complete&&e):d=!1;return d?(a.setAttributeNS(null,"d",c+" z"),a.setAttributeNS(null,"fill-rule","evenodd"),e?a:null):!1},drawRectangle:function(a,b){var c=this.getResolution(),d=(b.x-this.featureDx)/c+this.left,e=this.top-b.y/c;return this.inValidRange(d,e)?(a.setAttributeNS(null,"x",
2642 d),a.setAttributeNS(null,"y",e),a.setAttributeNS(null,"width",b.width/c),a.setAttributeNS(null,"height",b.height/c),a):!1},drawText:function(a,b,c){var d=!!b.labelOutlineWidth;if(d){var e=OpenLayers.Util.extend({},b);e.fontColor=e.labelOutlineColor;e.fontStrokeColor=e.labelOutlineColor;e.fontStrokeWidth=b.labelOutlineWidth;b.labelOutlineOpacity&&(e.fontOpacity=b.labelOutlineOpacity);delete e.labelOutlineWidth;this.drawText(a,e,c)}var f=this.getResolution(),e=(c.x-this.featureDx)/f+this.left,g=c.y/
2643 f-this.top,d=d?this.LABEL_OUTLINE_SUFFIX:this.LABEL_ID_SUFFIX,f=this.nodeFactory(a+d,"text");f.setAttributeNS(null,"x",e);f.setAttributeNS(null,"y",-g);b.fontColor&&f.setAttributeNS(null,"fill",b.fontColor);b.fontStrokeColor&&f.setAttributeNS(null,"stroke",b.fontStrokeColor);b.fontStrokeWidth&&f.setAttributeNS(null,"stroke-width",b.fontStrokeWidth);b.fontOpacity&&f.setAttributeNS(null,"opacity",b.fontOpacity);b.fontFamily&&f.setAttributeNS(null,"font-family",b.fontFamily);b.fontSize&&f.setAttributeNS(null,
2644 "font-size",b.fontSize);b.fontWeight&&f.setAttributeNS(null,"font-weight",b.fontWeight);b.fontStyle&&f.setAttributeNS(null,"font-style",b.fontStyle);!0===b.labelSelect?(f.setAttributeNS(null,"pointer-events","visible"),f._featureId=a):f.setAttributeNS(null,"pointer-events","none");g=b.labelAlign||OpenLayers.Renderer.defaultSymbolizer.labelAlign;f.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG.LABEL_ALIGN[g[0]]||"middle");!0===OpenLayers.IS_GECKO&&f.setAttributeNS(null,"dominant-baseline",
2645 OpenLayers.Renderer.SVG.LABEL_ALIGN[g[1]]||"central");for(var h=b.label.split("\n"),k=h.length;f.childNodes.length>k;)f.removeChild(f.lastChild);for(var l=0;l<k;l++){var m=this.nodeFactory(a+d+"_tspan_"+l,"tspan");!0===b.labelSelect&&(m._featureId=a,m._geometry=c,m._geometryClass=c.CLASS_NAME);!1===OpenLayers.IS_GECKO&&m.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG.LABEL_VSHIFT[g[1]]||"-35%");m.setAttribute("x",e);if(0==l){var n=OpenLayers.Renderer.SVG.LABEL_VFACTOR[g[1]];null==n&&
2646 (n=-0.5);m.setAttribute("dy",n*(k-1)+"em")}else m.setAttribute("dy","1em");m.textContent=""===h[l]?" ":h[l];m.parentNode||f.appendChild(m)}f.parentNode||this.textRoot.appendChild(f)},getComponentsString:function(a,b){for(var c=[],d=!0,e=a.length,f=[],g,h=0;h<e;h++)g=a[h],c.push(g),(g=this.getShortString(g))?f.push(g):(0<h&&this.getShortString(a[h-1])&&f.push(this.clipLine(a[h],a[h-1])),h<e-1&&this.getShortString(a[h+1])&&f.push(this.clipLine(a[h],a[h+1])),d=!1);return{path:f.join(b||","),complete:d}},
2647 clipLine:function(a,b){if(b.equals(a))return"";var c=this.getResolution(),d=this.MAX_PIXEL-this.translationParameters.x,e=this.MAX_PIXEL-this.translationParameters.y,f=(b.x-this.featureDx)/c+this.left,g=this.top-b.y/c,h=(a.x-this.featureDx)/c+this.left,c=this.top-a.y/c,k;if(h<-d||h>d)k=(c-g)/(h-f),h=0>h?-d:d,c=g+(h-f)*k;if(c<-e||c>e)k=(h-f)/(c-g),c=0>c?-e:e,h=f+(c-g)*k;return h+","+c},getShortString:function(a){var b=this.getResolution(),c=(a.x-this.featureDx)/b+this.left;a=this.top-a.y/b;return this.inValidRange(c,
2648 a)?c+","+a:!1},getPosition:function(a){return{x:parseFloat(a.getAttributeNS(null,"cx")),y:parseFloat(a.getAttributeNS(null,"cy"))}},importSymbol:function(a){this.defs||(this.defs=this.createDefs());var b=this.container.id+"-"+a,c=document.getElementById(b);if(null!=c)return c;var d=OpenLayers.Renderer.symbol[a];if(!d)throw Error(a+" is not a valid symbol name");a=this.nodeFactory(b,"symbol");var e=this.nodeFactory(null,"polygon");a.appendChild(e);for(var c=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,
2649 0,0),f=[],g,h,k=0;k<d.length;k+=2)g=d[k],h=d[k+1],c.left=Math.min(c.left,g),c.bottom=Math.min(c.bottom,h),c.right=Math.max(c.right,g),c.top=Math.max(c.top,h),f.push(g,",",h);e.setAttributeNS(null,"points",f.join(" "));d=c.getWidth();e=c.getHeight();a.setAttributeNS(null,"viewBox",[c.left-d,c.bottom-e,3*d,3*e].join(" "));this.symbolMetrics[b]=[Math.max(d,e),c.getCenterLonLat().lon,c.getCenterLonLat().lat];this.defs.appendChild(a);return a},getFeatureIdFromEvent:function(a){var b=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,
2650 arguments);b||(b=a.target,b=b.parentNode&&b!=this.rendererRoot?b.parentNode._featureId:void 0);return b},CLASS_NAME:"OpenLayers.Renderer.SVG"});OpenLayers.Renderer.SVG.LABEL_ALIGN={l:"start",r:"end",b:"bottom",t:"hanging"};OpenLayers.Renderer.SVG.LABEL_VSHIFT={t:"-70%",b:"0"};OpenLayers.Renderer.SVG.LABEL_VFACTOR={t:0,b:-1};OpenLayers.Renderer.SVG.preventDefault=function(a){OpenLayers.Event.preventDefault(a)};OpenLayers.Format.SLD.v1_0_0=OpenLayers.Class(OpenLayers.Format.SLD.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",CLASS_NAME:"OpenLayers.Format.SLD.v1_0_0"});OpenLayers.Format.OWSContext=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"0.3.1",getVersion:function(a,b){var c=OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(this,arguments);"0.3.0"===c&&(c=this.defaultVersion);return c},toContext:function(a){var b={};"OpenLayers.Map"==a.CLASS_NAME&&(b.bounds=a.getExtent(),b.maxExtent=a.maxExtent,b.projection=a.projection,b.size=a.getSize(),b.layers=a.layers);return b},CLASS_NAME:"OpenLayers.Format.OWSContext"});OpenLayers.Format.OWSContext.v0_3_1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{owc:"http://www.opengis.net/ows-context",gml:"http://www.opengis.net/gml",kml:"http://www.opengis.net/kml/2.2",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},VERSION:"0.3.1",schemaLocation:"http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",
2651 defaultPrefix:"owc",extractAttributes:!0,xy:!0,regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},featureNS:"http://mapserver.gis.umn.edu/mapserver",featureType:"vector",geometryName:"geometry",nestingLayerLookup:null,initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a]);OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this)},setNestingPath:function(a){if(a.layersContext)for(var b=0,c=a.layersContext.length;b<c;b++){var d=
2652 a.layersContext[b],e=[],f=a.title||"";a.metadata&&a.metadata.nestingPath&&(e=a.metadata.nestingPath.slice());""!=f&&e.push(f);d.metadata.nestingPath=e;d.layersContext&&this.setNestingPath(d)}},decomposeNestingPath:function(a){var b=[];if(OpenLayers.Util.isArray(a)){for(a=a.slice();0<a.length;)b.push(a.slice()),a.pop();b.reverse()}return b},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,
2653 b);this.setNestingPath({layersContext:b.layersContext});a=[];this.processLayer(a,b);delete b.layersContext;b.layersContext=a;return b},processLayer:function(a,b){if(b.layersContext)for(var c=0,d=b.layersContext.length;c<d;c++){var e=b.layersContext[c];a.push(e);e.layersContext&&this.processLayer(a,e)}},write:function(a,b){this.nestingLayerLookup={};b=b||{};OpenLayers.Util.applyDefaults(b,a);var c=this.writeNode("OWSContext",b);this.nestingLayerLookup=null;this.setAttributeNS(c,this.namespaces.xsi,
2654 "xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[c])},readers:{kml:{Document:function(a,b){b.features=(new OpenLayers.Format.KML({kmlns:this.namespaces.kml,extractStyles:!0})).read(a)}},owc:{OWSContext:function(a,b){this.readChildNodes(a,b)},General:function(a,b){this.readChildNodes(a,b)},ResourceList:function(a,b){this.readChildNodes(a,b)},Layer:function(a,b){var c={metadata:{},visibility:"1"!=a.getAttribute("hidden"),queryable:"1"==a.getAttribute("queryable"),
2655 opacity:null!=a.getAttribute("opacity")?parseFloat(a.getAttribute("opacity")):null,name:a.getAttribute("name"),categoryLayer:null==a.getAttribute("name"),formats:[],styles:[]};b.layersContext||(b.layersContext=[]);b.layersContext.push(c);this.readChildNodes(a,c)},InlineGeometry:function(a,b){b.features=[];var c=this.getElementsByTagNameNS(a,this.namespaces.gml,"featureMember"),d;1<=c.length&&(d=c[0]);d&&d.firstChild&&(c=d.firstChild.nextSibling?d.firstChild.nextSibling:d.firstChild,this.setNamespace("feature",
2656 c.namespaceURI),this.featureType=c.localName||c.nodeName.split(":").pop(),this.readChildNodes(a,b))},Server:function(a,b){if(!b.service&&!b.version||b.service!=OpenLayers.Format.Context.serviceTypes.WMS)b.service=a.getAttribute("service"),b.version=a.getAttribute("version"),this.readChildNodes(a,b)},Name:function(a,b){b.name=this.getChildValue(a);this.readChildNodes(a,b)},Title:function(a,b){b.title=this.getChildValue(a);this.readChildNodes(a,b)},StyleList:function(a,b){this.readChildNodes(a,b.styles)},
2657 Style:function(a,b){var c={};b.push(c);this.readChildNodes(a,c)},LegendURL:function(a,b){var c={};b.legend=c;this.readChildNodes(a,c)},OnlineResource:function(a,b){b.url=this.getAttributeNS(a,this.namespaces.xlink,"href");this.readChildNodes(a,b)}},ows:OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,gml:OpenLayers.Format.GML.v2.prototype.readers.gml,sld:OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,feature:OpenLayers.Format.GML.v2.prototype.readers.feature},writers:{owc:{OWSContext:function(a){var b=
2658 this.createElementNSPlus("OWSContext",{attributes:{version:this.VERSION,id:a.id||OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")}});this.writeNode("General",a,b);this.writeNode("ResourceList",a,b);return b},General:function(a){var b=this.createElementNSPlus("General");this.writeNode("ows:BoundingBox",a,b);this.writeNode("ows:Title",a.title||"OpenLayers OWSContext",b);return b},ResourceList:function(a){for(var b=this.createElementNSPlus("ResourceList"),c=0,d=a.layers.length;c<d;c++){var e=
2659 a.layers[c],f=this.decomposeNestingPath(e.metadata.nestingPath);this.writeNode("_Layer",{layer:e,subPaths:f},b)}return b},Server:function(a){var b=this.createElementNSPlus("Server",{attributes:{version:a.version,service:a.service}});this.writeNode("OnlineResource",a,b);return b},OnlineResource:function(a){return this.createElementNSPlus("OnlineResource",{attributes:{"xlink:href":a.url}})},InlineGeometry:function(a){var b=this.createElementNSPlus("InlineGeometry"),c=a.getDataExtent();null!==c&&this.writeNode("gml:boundedBy",
2660 c,b);for(var c=0,d=a.features.length;c<d;c++)this.writeNode("gml:featureMember",a.features[c],b);return b},StyleList:function(a){for(var b=this.createElementNSPlus("StyleList"),c=0,d=a.length;c<d;c++)this.writeNode("Style",a[c],b);return b},Style:function(a){var b=this.createElementNSPlus("Style");this.writeNode("Name",a,b);this.writeNode("Title",a,b);a.legend&&this.writeNode("LegendURL",a,b);return b},Name:function(a){return this.createElementNSPlus("Name",{value:a.name})},Title:function(a){return this.createElementNSPlus("Title",
2661 {value:a.title})},LegendURL:function(a){var b=this.createElementNSPlus("LegendURL");this.writeNode("OnlineResource",a.legend,b);return b},_WMS:function(a){var b=this.createElementNSPlus("Layer",{attributes:{name:a.params.LAYERS,queryable:a.queryable?"1":"0",hidden:a.visibility?"0":"1",opacity:a.hasOwnProperty("opacity")?a.opacity:null}});this.writeNode("ows:Title",a.name,b);this.writeNode("ows:OutputFormat",a.params.FORMAT,b);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WMS,
2662 version:a.params.VERSION,url:a.url},b);a.metadata.styles&&0<a.metadata.styles.length&&this.writeNode("StyleList",a.metadata.styles,b);return b},_Layer:function(a){var b,c,d;b=a.layer;c=a.subPaths;d=null;0<c.length?(b=c[0].join("/"),c=b.lastIndexOf("/"),d=this.nestingLayerLookup[b],c=0<c?b.substring(c+1,b.length):b,d||(d=this.createElementNSPlus("Layer"),this.writeNode("ows:Title",c,d),this.nestingLayerLookup[b]=d),a.subPaths.shift(),this.writeNode("_Layer",a,d)):(b instanceof OpenLayers.Layer.WMS?
2663 d=this.writeNode("_WMS",b):b instanceof OpenLayers.Layer.Vector&&(b.protocol instanceof OpenLayers.Protocol.WFS.v1?d=this.writeNode("_WFS",b):b.protocol instanceof OpenLayers.Protocol.HTTP?b.protocol.format instanceof OpenLayers.Format.GML?(b.protocol.format.version="2.1.2",d=this.writeNode("_GML",b)):b.protocol.format instanceof OpenLayers.Format.KML&&(b.protocol.format.version="2.2",d=this.writeNode("_KML",b)):(this.setNamespace("feature",this.featureNS),d=this.writeNode("_InlineGeometry",b))),
2664 b.options.maxScale&&this.writeNode("sld:MinScaleDenominator",b.options.maxScale,d),b.options.minScale&&this.writeNode("sld:MaxScaleDenominator",b.options.minScale,d),this.nestingLayerLookup[b.name]=d);return d},_WFS:function(a){var b=this.createElementNSPlus("Layer",{attributes:{name:a.protocol.featurePrefix+":"+a.protocol.featureType,hidden:a.visibility?"0":"1"}});this.writeNode("ows:Title",a.name,b);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WFS,version:a.protocol.version,
2665 url:a.protocol.url},b);return b},_InlineGeometry:function(a){var b=this.createElementNSPlus("Layer",{attributes:{name:this.featureType,hidden:a.visibility?"0":"1"}});this.writeNode("ows:Title",a.name,b);this.writeNode("InlineGeometry",a,b);return b},_GML:function(a){var b=this.createElementNSPlus("Layer");this.writeNode("ows:Title",a.name,b);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.GML,url:a.protocol.url,version:a.protocol.format.version},b);return b},_KML:function(a){var b=
2666 this.createElementNSPlus("Layer");this.writeNode("ows:Title",a.name,b);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.KML,version:a.protocol.format.version,url:a.protocol.url},b);return b}},gml:OpenLayers.Util.applyDefaults({boundedBy:function(a){var b=this.createElementNSPlus("gml:boundedBy");this.writeNode("gml:Box",a,b);return b}},OpenLayers.Format.GML.v2.prototype.writers.gml),ows:OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,sld:OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,
2667 feature:OpenLayers.Format.GML.v2.prototype.writers.feature},CLASS_NAME:"OpenLayers.Format.OWSContext.v0_3_1"});OpenLayers.Popup=OpenLayers.Class({events:null,id:"",lonlat:null,div:null,contentSize:null,size:null,contentHTML:null,backgroundColor:"",opacity:"",border:"",contentDiv:null,groupDiv:null,closeDiv:null,autoSize:!1,minSize:null,maxSize:null,displayClass:"olPopup",contentDisplayClass:"olPopupContent",padding:0,disableFirefoxOverflowHack:!1,fixPadding:function(){"number"==typeof this.padding&&(this.padding=new OpenLayers.Bounds(this.padding,this.padding,this.padding,this.padding))},panMapIfOutOfView:!1,
2668 keepInMap:!1,closeOnMove:!1,map:null,initialize:function(a,b,c,d,e,f){null==a&&(a=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_"));this.id=a;this.lonlat=b;this.contentSize=null!=c?c:new OpenLayers.Size(OpenLayers.Popup.WIDTH,OpenLayers.Popup.HEIGHT);null!=d&&(this.contentHTML=d);this.backgroundColor=OpenLayers.Popup.COLOR;this.opacity=OpenLayers.Popup.OPACITY;this.border=OpenLayers.Popup.BORDER;this.div=OpenLayers.Util.createDiv(this.id,null,null,null,null,null,"hidden");this.div.className=this.displayClass;
2669 this.groupDiv=OpenLayers.Util.createDiv(this.id+"_GroupDiv",null,null,null,"relative",null,"hidden");a=this.div.id+"_contentDiv";this.contentDiv=OpenLayers.Util.createDiv(a,null,this.contentSize.clone(),null,"relative");this.contentDiv.className=this.contentDisplayClass;this.groupDiv.appendChild(this.contentDiv);this.div.appendChild(this.groupDiv);e&&this.addCloseBox(f);this.registerEvents()},destroy:function(){this.border=this.opacity=this.backgroundColor=this.contentHTML=this.size=this.lonlat=this.id=
2670 null;this.closeOnMove&&this.map&&this.map.events.unregister("movestart",this,this.hide);this.events.destroy();this.events=null;this.closeDiv&&(OpenLayers.Event.stopObservingElement(this.closeDiv),this.groupDiv.removeChild(this.closeDiv));this.closeDiv=null;this.div.removeChild(this.groupDiv);this.groupDiv=null;null!=this.map&&this.map.removePopup(this);this.panMapIfOutOfView=this.padding=this.maxSize=this.minSize=this.autoSize=this.div=this.map=null},draw:function(a){null==a&&null!=this.lonlat&&null!=
2671 this.map&&(a=this.map.getLayerPxFromLonLat(this.lonlat));this.closeOnMove&&this.map.events.register("movestart",this,this.hide);this.disableFirefoxOverflowHack||"firefox"!=OpenLayers.BROWSER_NAME||(this.map.events.register("movestart",this,function(){var a=document.defaultView.getComputedStyle(this.contentDiv,null).getPropertyValue("overflow");"hidden"!=a&&(this.contentDiv._oldOverflow=a,this.contentDiv.style.overflow="hidden")}),this.map.events.register("moveend",this,function(){var a=this.contentDiv._oldOverflow;
2672 a&&(this.contentDiv.style.overflow=a,this.contentDiv._oldOverflow=null)}));this.moveTo(a);this.autoSize||this.size||this.setSize(this.contentSize);this.setBackgroundColor();this.setOpacity();this.setBorder();this.setContentHTML();this.panMapIfOutOfView&&this.panIntoView();return this.div},updatePosition:function(){if(this.lonlat&&this.map){var a=this.map.getLayerPxFromLonLat(this.lonlat);a&&this.moveTo(a)}},moveTo:function(a){null!=a&&null!=this.div&&(this.div.style.left=a.x+"px",this.div.style.top=
2673 a.y+"px")},visible:function(){return OpenLayers.Element.visible(this.div)},toggle:function(){this.visible()?this.hide():this.show()},show:function(){this.div.style.display="";this.panMapIfOutOfView&&this.panIntoView()},hide:function(){this.div.style.display="none"},setSize:function(a){this.size=a.clone();var b=this.getContentDivPadding(),c=b.left+b.right,d=b.top+b.bottom;this.fixPadding();c+=this.padding.left+this.padding.right;d+=this.padding.top+this.padding.bottom;if(this.closeDiv)var e=parseInt(this.closeDiv.style.width),
2674 c=c+(e+b.right);this.size.w+=c;this.size.h+=d;"msie"==OpenLayers.BROWSER_NAME&&(this.contentSize.w+=b.left+b.right,this.contentSize.h+=b.bottom+b.top);null!=this.div&&(this.div.style.width=this.size.w+"px",this.div.style.height=this.size.h+"px");null!=this.contentDiv&&(this.contentDiv.style.width=a.w+"px",this.contentDiv.style.height=a.h+"px")},updateSize:function(){var a="<div class='"+this.contentDisplayClass+"'>"+this.contentDiv.innerHTML+"</div>",b=this.map?this.map.div:document.body,c=OpenLayers.Util.getRenderedDimensions(a,
2675 null,{displayClass:this.displayClass,containerElement:b}),d=this.getSafeContentSize(c),e=null;d.equals(c)?e=c:(c={w:d.w<c.w?d.w:null,h:d.h<c.h?d.h:null},c.w&&c.h?e=d:(a=OpenLayers.Util.getRenderedDimensions(a,c,{displayClass:this.contentDisplayClass,containerElement:b}),"hidden"!=OpenLayers.Element.getStyle(this.contentDiv,"overflow")&&a.equals(d)&&(d=OpenLayers.Util.getScrollbarWidth(),c.w?a.h+=d:a.w+=d),e=this.getSafeContentSize(a)));this.setSize(e)},setBackgroundColor:function(a){void 0!=a&&(this.backgroundColor=
2676 a);null!=this.div&&(this.div.style.backgroundColor=this.backgroundColor)},setOpacity:function(a){void 0!=a&&(this.opacity=a);null!=this.div&&(this.div.style.opacity=this.opacity,this.div.style.filter="alpha(opacity="+100*this.opacity+")")},setBorder:function(a){void 0!=a&&(this.border=a);null!=this.div&&(this.div.style.border=this.border)},setContentHTML:function(a){null!=a&&(this.contentHTML=a);null!=this.contentDiv&&(null!=this.contentHTML&&this.contentHTML!=this.contentDiv.innerHTML)&&(this.contentDiv.innerHTML=
2677 this.contentHTML,this.autoSize&&(this.registerImageListeners(),this.updateSize()))},registerImageListeners:function(){for(var a=function(){null!==this.popup.id&&(this.popup.updateSize(),this.popup.visible()&&this.popup.panMapIfOutOfView&&this.popup.panIntoView(),OpenLayers.Event.stopObserving(this.img,"load",this.img._onImgLoad))},b=this.contentDiv.getElementsByTagName("img"),c=0,d=b.length;c<d;c++){var e=b[c];if(0==e.width||0==e.height)e._onImgLoad=OpenLayers.Function.bind(a,{popup:this,img:e}),
2678 OpenLayers.Event.observe(e,"load",e._onImgLoad)}},getSafeContentSize:function(a){a=a.clone();var b=this.getContentDivPadding(),c=b.left+b.right,d=b.top+b.bottom;this.fixPadding();c+=this.padding.left+this.padding.right;d+=this.padding.top+this.padding.bottom;if(this.closeDiv)var e=parseInt(this.closeDiv.style.width),c=c+(e+b.right);this.minSize&&(a.w=Math.max(a.w,this.minSize.w-c),a.h=Math.max(a.h,this.minSize.h-d));this.maxSize&&(a.w=Math.min(a.w,this.maxSize.w-c),a.h=Math.min(a.h,this.maxSize.h-
2679 d));if(this.map&&this.map.size){e=b=0;if(this.keepInMap&&!this.panMapIfOutOfView)switch(e=this.map.getPixelFromLonLat(this.lonlat),this.relativePosition){case "tr":b=e.x;e=this.map.size.h-e.y;break;case "tl":b=this.map.size.w-e.x;e=this.map.size.h-e.y;break;case "bl":b=this.map.size.w-e.x;e=e.y;break;case "br":b=e.x;e=e.y;break;default:b=e.x,e=this.map.size.h-e.y}d=this.map.size.h-this.map.paddingForPopups.top-this.map.paddingForPopups.bottom-d-e;a.w=Math.min(a.w,this.map.size.w-this.map.paddingForPopups.left-
2680 this.map.paddingForPopups.right-c-b);a.h=Math.min(a.h,d)}return a},getContentDivPadding:function(){var a=this._contentDivPadding;a||(null==this.div.parentNode&&(this.div.style.display="none",document.body.appendChild(this.div)),this._contentDivPadding=a=new OpenLayers.Bounds(OpenLayers.Element.getStyle(this.contentDiv,"padding-left"),OpenLayers.Element.getStyle(this.contentDiv,"padding-bottom"),OpenLayers.Element.getStyle(this.contentDiv,"padding-right"),OpenLayers.Element.getStyle(this.contentDiv,
2681 "padding-top")),this.div.parentNode==document.body&&(document.body.removeChild(this.div),this.div.style.display=""));return a},addCloseBox:function(a){this.closeDiv=OpenLayers.Util.createDiv(this.id+"_close",null,{w:17,h:17});this.closeDiv.className="olPopupCloseBox";var b=this.getContentDivPadding();this.closeDiv.style.right=b.right+"px";this.closeDiv.style.top=b.top+"px";this.groupDiv.appendChild(this.closeDiv);a=a||function(a){this.hide();OpenLayers.Event.stop(a)};OpenLayers.Event.observe(this.closeDiv,
2682 "touchend",OpenLayers.Function.bindAsEventListener(a,this));OpenLayers.Event.observe(this.closeDiv,"click",OpenLayers.Function.bindAsEventListener(a,this))},panIntoView:function(){var a=this.map.getSize(),b=this.map.getViewPortPxFromLayerPx(new OpenLayers.Pixel(parseInt(this.div.style.left),parseInt(this.div.style.top))),c=b.clone();b.x<this.map.paddingForPopups.left?c.x=this.map.paddingForPopups.left:b.x+this.size.w>a.w-this.map.paddingForPopups.right&&(c.x=a.w-this.map.paddingForPopups.right-this.size.w);
2683 b.y<this.map.paddingForPopups.top?c.y=this.map.paddingForPopups.top:b.y+this.size.h>a.h-this.map.paddingForPopups.bottom&&(c.y=a.h-this.map.paddingForPopups.bottom-this.size.h);this.map.pan(b.x-c.x,b.y-c.y)},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,!0);this.events.on({mousedown:this.onmousedown,mousemove:this.onmousemove,mouseup:this.onmouseup,click:this.onclick,mouseout:this.onmouseout,dblclick:this.ondblclick,touchstart:function(a){OpenLayers.Event.stop(a,!0)},
2684 scope:this})},onmousedown:function(a){this.mousedown=!0;OpenLayers.Event.stop(a,!0)},onmousemove:function(a){this.mousedown&&OpenLayers.Event.stop(a,!0)},onmouseup:function(a){this.mousedown&&(this.mousedown=!1,OpenLayers.Event.stop(a,!0))},onclick:function(a){OpenLayers.Event.stop(a,!0)},onmouseout:function(a){this.mousedown=!1},ondblclick:function(a){OpenLayers.Event.stop(a,!0)},CLASS_NAME:"OpenLayers.Popup"});OpenLayers.Popup.WIDTH=200;OpenLayers.Popup.HEIGHT=200;OpenLayers.Popup.COLOR="white";
2685 OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:!1,draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.eTop||(this.eTop=document.createElement("div"),this.eTop.className=this.displayClass+"Top",this.div.appendChild(this.eTop),this.eTop.style.visibility=""==this.topOutUnits||""==this.topInUnits?"hidden":"visible",this.eBottom=document.createElement("div"),
2686 this.eBottom.className=this.displayClass+"Bottom",this.div.appendChild(this.eBottom),this.eBottom.style.visibility=""==this.bottomOutUnits||""==this.bottomInUnits?"hidden":"visible");this.map.events.register("moveend",this,this.update);this.update();return this.div},getBarLen:function(a){var b=parseInt(Math.log(a)/Math.log(10)),b=Math.pow(10,b);a=parseInt(a/b);return(5<a?5:2<a?2:1)*b},update:function(){var a=this.map.getResolution();if(a){var b=this.map.getUnits(),c=OpenLayers.INCHES_PER_UNIT,d=this.maxWidth*
2687 a*c[b],e=1;!0===this.geodesic&&(e=(this.map.getGeodesicPixelSize().w||1E-6)*this.maxWidth/(d/c.km),d*=e);var f,g;1E5<d?(f=this.topOutUnits,g=this.bottomOutUnits):(f=this.topInUnits,g=this.bottomInUnits);var h=d/c[f],k=d/c[g],d=this.getBarLen(h),l=this.getBarLen(k),h=d/c[b]*c[f],k=l/c[b]*c[g],b=h/a/e,a=k/a/e;"visible"==this.eBottom.style.visibility&&(this.eBottom.style.width=Math.round(a)+"px",this.eBottom.innerHTML=l+" "+g);"visible"==this.eTop.style.visibility&&(this.eTop.style.width=Math.round(b)+
2688 "px",this.eTop.innerHTML=d+" "+f)}},CLASS_NAME:"OpenLayers.Control.ScaleLine"});OpenLayers.Icon=OpenLayers.Class({url:null,size:null,offset:null,calculateOffset:null,imageDiv:null,px:null,initialize:function(a,b,c,d){this.url=a;this.size=b||{w:20,h:20};this.offset=c||{x:-(this.size.w/2),y:-(this.size.h/2)};this.calculateOffset=d;a=OpenLayers.Util.createUniqueID("OL_Icon_");this.imageDiv=OpenLayers.Util.createAlphaImageDiv(a)},destroy:function(){this.erase();OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);this.imageDiv.innerHTML="";this.imageDiv=null},clone:function(){return new OpenLayers.Icon(this.url,
2689 this.size,this.offset,this.calculateOffset)},setSize:function(a){null!=a&&(this.size=a);this.draw()},setUrl:function(a){null!=a&&(this.url=a);this.draw()},draw:function(a){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,this.size,this.url,"absolute");this.moveTo(a);return this.imageDiv},erase:function(){null!=this.imageDiv&&null!=this.imageDiv.parentNode&&OpenLayers.Element.remove(this.imageDiv)},setOpacity:function(a){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,null,null,
2690 null,null,null,a)},moveTo:function(a){null!=a&&(this.px=a);null!=this.imageDiv&&(null==this.px?this.display(!1):(this.calculateOffset&&(this.offset=this.calculateOffset(this.size)),OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,{x:this.px.x+this.offset.x,y:this.px.y+this.offset.y})))},display:function(a){this.imageDiv.style.display=a?"":"none"},isDrawn:function(){return this.imageDiv&&this.imageDiv.parentNode&&11!=this.imageDiv.parentNode.nodeType},CLASS_NAME:"OpenLayers.Icon"});OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(a,b){this.lonlat=a;var c=b?b:OpenLayers.Marker.defaultIcon();null==this.icon?this.icon=c:(this.icon.url=c.url,this.icon.size=c.size,this.icon.offset=c.offset,this.icon.calculateOffset=c.calculateOffset);this.events=new OpenLayers.Events(this,this.icon.imageDiv)},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;null!=this.icon&&(this.icon.destroy(),this.icon=null)},
2691 draw:function(a){return this.icon.draw(a)},erase:function(){null!=this.icon&&this.icon.erase()},moveTo:function(a){null!=a&&null!=this.icon&&this.icon.moveTo(a);this.lonlat=this.map.getLonLatFromLayerPx(a)},isDrawn:function(){return this.icon&&this.icon.isDrawn()},onScreen:function(){var a=!1;this.map&&(a=this.map.getExtent().containsLonLat(this.lonlat));return a},inflate:function(a){this.icon&&this.icon.setSize({w:this.icon.size.w*a,h:this.icon.size.h*a})},setOpacity:function(a){this.icon.setOpacity(a)},
2692 setUrl:function(a){this.icon.setUrl(a)},display:function(a){this.icon.display(a)},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"),{w:21,h:25},{x:-10.5,y:-25})};OpenLayers.Layer.TileCache=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,format:"image/png",serverResolutions:null,initialize:function(a,b,c,d){this.layername=c;OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a,b,{},d]);this.extension=this.format.split("/")[1].toLowerCase();this.extension="jpg"==this.extension?"jpeg":this.extension},clone:function(a){null==a&&(a=new OpenLayers.Layer.TileCache(this.name,this.url,this.layername,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,
2693 [a])},getURL:function(a){var b=this.getServerResolution(),c=this.maxExtent,d=this.tileSize,e=Math.round((a.left-c.left)/(b*d.w));a=Math.round((a.bottom-c.bottom)/(b*d.h));b=null!=this.serverResolutions?OpenLayers.Util.indexOf(this.serverResolutions,b):this.map.getZoom();e=[this.layername,OpenLayers.Number.zeroPad(b,2),OpenLayers.Number.zeroPad(parseInt(e/1E6),3),OpenLayers.Number.zeroPad(parseInt(e/1E3)%1E3,3),OpenLayers.Number.zeroPad(parseInt(e)%1E3,3),OpenLayers.Number.zeroPad(parseInt(a/1E6),
2694 3),OpenLayers.Number.zeroPad(parseInt(a/1E3)%1E3,3),OpenLayers.Number.zeroPad(parseInt(a)%1E3,3)+"."+this.extension].join("/");b=this.url;OpenLayers.Util.isArray(b)&&(b=this.selectUrl(e,b));b="/"==b.charAt(b.length-1)?b:b+"/";return b+e},CLASS_NAME:"OpenLayers.Layer.TileCache"});OpenLayers.Strategy.Paging=OpenLayers.Class(OpenLayers.Strategy,{features:null,length:10,num:null,paging:!1,activate:function(){var a=OpenLayers.Strategy.prototype.activate.call(this);if(a)this.layer.events.on({beforefeaturesadded:this.cacheFeatures,scope:this});return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&(this.clearCache(),this.layer.events.un({beforefeaturesadded:this.cacheFeatures,scope:this}));return a},cacheFeatures:function(a){this.paging||(this.clearCache(),
2695 this.features=a.features,this.pageNext(a))},clearCache:function(){if(this.features)for(var a=0;a<this.features.length;++a)this.features[a].destroy();this.num=this.features=null},pageCount:function(){return Math.ceil((this.features?this.features.length:0)/this.length)},pageNum:function(){return this.num},pageLength:function(a){a&&0<a&&(this.length=a);return this.length},pageNext:function(a){var b=!1;this.features&&(null===this.num&&(this.num=-1),b=this.page((this.num+1)*this.length,a));return b},pagePrevious:function(){var a=
2696 !1;this.features&&(null===this.num&&(this.num=this.pageCount()),a=this.page((this.num-1)*this.length));return a},page:function(a,b){var c=!1;if(this.features&&0<=a&&a<this.features.length){var d=Math.floor(a/this.length);d!=this.num&&(this.paging=!0,c=this.features.slice(a,a+this.length),this.layer.removeFeatures(this.layer.features),this.num=d,b&&b.features?b.features=c:this.layer.addFeatures(c),this.paging=!1,c=!0)}return c},CLASS_NAME:"OpenLayers.Strategy.Paging"});OpenLayers.Control.DragFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,onStart:function(a,b){},onDrag:function(a,b){},onComplete:function(a,b){},onEnter:function(a){},onLeave:function(a){},documentDrag:!1,layer:null,feature:null,dragCallbacks:{},featureCallbacks:{},lastPixel:null,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);this.layer=a;this.handlers={drag:new OpenLayers.Handler.Drag(this,OpenLayers.Util.extend({down:this.downFeature,move:this.moveFeature,
2697 up:this.upFeature,out:this.cancel,done:this.doneDragging},this.dragCallbacks),{documentDrag:this.documentDrag}),feature:new OpenLayers.Handler.Feature(this,this.layer,OpenLayers.Util.extend({click:this.clickFeature,clickout:this.clickoutFeature,over:this.overFeature,out:this.outFeature},this.featureCallbacks),{geometryTypes:this.geometryTypes})}},clickFeature:function(a){this.handlers.feature.touch&&(!this.over&&this.overFeature(a))&&(this.handlers.drag.dragstart(this.handlers.feature.evt),this.handlers.drag.stopDown=
2698 !1)},clickoutFeature:function(a){this.handlers.feature.touch&&this.over&&(this.outFeature(a),this.handlers.drag.stopDown=!0)},destroy:function(){this.layer=null;OpenLayers.Control.prototype.destroy.apply(this,[])},activate:function(){return this.handlers.feature.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments)},deactivate:function(){this.handlers.drag.deactivate();this.handlers.feature.deactivate();this.feature=null;this.dragging=!1;this.lastPixel=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,
2699 this.displayClass+"Over");return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},overFeature:function(a){var b=!1;this.handlers.drag.dragging?this.over=this.feature.id==a.id?!0:!1:(this.feature=a,this.handlers.drag.activate(),this.over=b=!0,OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass+"Over"),this.onEnter(a));return b},downFeature:function(a){this.lastPixel=a;this.onStart(this.feature,a)},moveFeature:function(a){var b=this.map.getResolution();this.feature.geometry.move(b*
2700 (a.x-this.lastPixel.x),b*(this.lastPixel.y-a.y));this.layer.drawFeature(this.feature);this.lastPixel=a;this.onDrag(this.feature,a)},upFeature:function(a){this.over||this.handlers.drag.deactivate()},doneDragging:function(a){this.onComplete(this.feature,a)},outFeature:function(a){this.handlers.drag.dragging?this.feature.id==a.id&&(this.over=!1):(this.over=!1,this.handlers.drag.deactivate(),OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over"),this.onLeave(a),this.feature=null)},
2701 cancel:function(){this.handlers.drag.deactivate();this.over=!1},setMap:function(a){this.handlers.drag.setMap(a);this.handlers.feature.setMap(a);OpenLayers.Control.prototype.setMap.apply(this,arguments)},CLASS_NAME:"OpenLayers.Control.DragFeature"});OpenLayers.Control.TransformFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,layer:null,preserveAspectRatio:!1,rotate:!0,feature:null,renderIntent:"temporary",rotationHandleSymbolizer:null,box:null,center:null,scale:1,ratio:1,rotation:0,handles:null,rotationHandles:null,dragControl:null,irregular:!1,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);this.layer=a;this.rotationHandleSymbolizer||(this.rotationHandleSymbolizer={stroke:!1,pointRadius:10,fillOpacity:0,
2702 cursor:"pointer"});this.createBox();this.createControl()},activate:function(){var a=!1;OpenLayers.Control.prototype.activate.apply(this,arguments)&&(this.dragControl.activate(),this.layer.addFeatures([this.box]),this.rotate&&this.layer.addFeatures(this.rotationHandles),this.layer.addFeatures(this.handles),a=!0);return a},deactivate:function(){var a=!1;OpenLayers.Control.prototype.deactivate.apply(this,arguments)&&(this.layer.removeFeatures(this.handles),this.rotate&&this.layer.removeFeatures(this.rotationHandles),
2703 this.layer.removeFeatures([this.box]),this.dragControl.deactivate(),a=!0);return a},setMap:function(a){this.dragControl.setMap(a);OpenLayers.Control.prototype.setMap.apply(this,arguments)},setFeature:function(a,b){b=OpenLayers.Util.applyDefaults(b,{rotation:0,scale:1,ratio:1});var c=this.rotation,d=this.center;OpenLayers.Util.extend(this,b);if(!1!==this.events.triggerEvent("beforesetfeature",{feature:a})){this.feature=a;this.activate();this._setfeature=!0;var e=this.feature.geometry.getBounds();this.box.move(e.getCenterLonLat());
2704 this.box.geometry.rotate(-c,d);this._angle=0;this.rotation?(c=a.geometry.clone(),c.rotate(-this.rotation,this.center),c=new OpenLayers.Feature.Vector(c.getBounds().toGeometry()),c.geometry.rotate(this.rotation,this.center),this.box.geometry.rotate(this.rotation,this.center),this.box.move(c.geometry.getBounds().getCenterLonLat()),c=c.geometry.components[0].components[0].getBounds().getCenterLonLat()):c=new OpenLayers.LonLat(e.left,e.bottom);this.handles[0].move(c);delete this._setfeature;this.events.triggerEvent("setfeature",
2705 {feature:a})}},unsetFeature:function(){this.active?this.deactivate():(this.feature=null,this.rotation=0,this.ratio=this.scale=1)},createBox:function(){var a=this;this.center=new OpenLayers.Geometry.Point(0,0);this.box=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([new OpenLayers.Geometry.Point(-1,-1),new OpenLayers.Geometry.Point(0,-1),new OpenLayers.Geometry.Point(1,-1),new OpenLayers.Geometry.Point(1,0),new OpenLayers.Geometry.Point(1,1),new OpenLayers.Geometry.Point(0,1),new OpenLayers.Geometry.Point(-1,
2706 1),new OpenLayers.Geometry.Point(-1,0),new OpenLayers.Geometry.Point(-1,-1)]),null,"string"==typeof this.renderIntent?null:this.renderIntent);this.box.geometry.move=function(b,c){a._moving=!0;OpenLayers.Geometry.LineString.prototype.move.apply(this,arguments);a.center.move(b,c);delete a._moving};for(var b=function(a,b){OpenLayers.Geometry.Point.prototype.move.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.move(a,b);this._handle.geometry.move(a,b)},c=function(a,b,c){OpenLayers.Geometry.Point.prototype.resize.apply(this,
2707 arguments);this._rotationHandle&&this._rotationHandle.geometry.resize(a,b,c);this._handle.geometry.resize(a,b,c)},d=function(a,b){OpenLayers.Geometry.Point.prototype.rotate.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.rotate(a,b);this._handle.geometry.rotate(a,b)},e=function(b,c){var d=this.x,e=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,b,c);if(!a._moving){var f=a.dragControl.handlers.drag.evt,g=!(!a._setfeature&&a.preserveAspectRatio)&&!(f&&f.shiftKey),
2708 h=new OpenLayers.Geometry.Point(d,e),f=a.center;this.rotate(-a.rotation,f);h.rotate(-a.rotation,f);var k=this.x-f.x,l=this.y-f.y,m=k-(this.x-h.x),n=l-(this.y-h.y);a.irregular&&!a._setfeature&&(k-=(this.x-h.x)/2,l-=(this.y-h.y)/2);this.x=d;this.y=e;h=1;g?(l=1E-5>Math.abs(n)?1:l/n,h=(1E-5>Math.abs(m)?1:k/m)/l):(m=Math.sqrt(m*m+n*n),l=Math.sqrt(k*k+l*l)/m);a._moving=!0;a.box.geometry.rotate(-a.rotation,f);delete a._moving;a.box.geometry.resize(l,f,h);a.box.geometry.rotate(a.rotation,f);a.transformFeature({scale:l,
2709 ratio:h});a.irregular&&!a._setfeature&&(k=f.clone(),k.x+=1E-5>Math.abs(d-f.x)?0:this.x-d,k.y+=1E-5>Math.abs(e-f.y)?0:this.y-e,a.box.geometry.move(this.x-d,this.y-e),a.transformFeature({center:k}))}},f=function(b,c){var d=this.x,e=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,b,c);if(!a._moving){var f=a.dragControl.handlers.drag.evt,f=f&&f.shiftKey?45:1,g=a.center,h=this.x-g.x,k=this.y-g.y;this.x=d;this.y=e;d=Math.atan2(k-c,h-b);d=Math.atan2(k,h)-d;d*=180/Math.PI;a._angle=(a._angle+d)%
2710 360;d=a.rotation%f;if(Math.abs(a._angle)>=f||0!==d)d=Math.round(a._angle/f)*f-d,a._angle=0,a.box.geometry.rotate(d,g),a.transformFeature({rotation:d})}},g=Array(8),h=Array(4),k,l,m,n="sw s se e ne n nw w".split(" "),p=0;8>p;++p)k=this.box.geometry.components[p],l=new OpenLayers.Feature.Vector(k.clone(),{role:n[p]+"-resize"},"string"==typeof this.renderIntent?null:this.renderIntent),0==p%2&&(m=new OpenLayers.Feature.Vector(k.clone(),{role:n[p]+"-rotate"},"string"==typeof this.rotationHandleSymbolizer?
2711 null:this.rotationHandleSymbolizer),m.geometry.move=f,k._rotationHandle=m,h[p/2]=m),k.move=b,k.resize=c,k.rotate=d,l.geometry.move=e,k._handle=l,g[p]=l;this.rotationHandles=h;this.handles=g},createControl:function(){var a=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:!0,moveFeature:function(b){this.feature===a.feature&&(this.feature=a.box);OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments)},onDrag:function(b,c){b===a.box&&a.transformFeature({center:a.center})},
2712 onStart:function(b,c){var d=!a.geometryTypes||-1!==OpenLayers.Util.indexOf(a.geometryTypes,b.geometry.CLASS_NAME),e=OpenLayers.Util.indexOf(a.handles,b),e=e+OpenLayers.Util.indexOf(a.rotationHandles,b);b!==a.feature&&(b!==a.box&&-2==e&&d)&&a.setFeature(b)},onComplete:function(b,c){a.events.triggerEvent("transformcomplete",{feature:a.feature})}})},drawHandles:function(){for(var a=this.layer,b=0;8>b;++b)this.rotate&&0===b%2&&a.drawFeature(this.rotationHandles[b/2],this.rotationHandleSymbolizer),a.drawFeature(this.handles[b],
2713 this.renderIntent)},transformFeature:function(a){if(!this._setfeature){this.scale*=a.scale||1;this.ratio*=a.ratio||1;var b=this.rotation;this.rotation=(this.rotation+(a.rotation||0))%360;if(!1!==this.events.triggerEvent("beforetransform",a)){var c=this.feature,d=c.geometry,e=this.center;d.rotate(-b,e);a.scale||a.ratio?d.resize(a.scale,e,a.ratio):a.center&&c.move(a.center.getBounds().getCenterLonLat());d.rotate(this.rotation,e);this.layer.drawFeature(c);c.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",
2714 a)}}this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles()},destroy:function(){for(var a,b=0;8>b;++b)a=this.box.geometry.components[b],a._handle.destroy(),a._handle=null,a._rotationHandle&&a._rotationHandle.destroy(),a._rotationHandle=null;this.rotationHandles=this.rotationHandleSymbolizer=this.handles=this.feature=this.center=null;this.box.destroy();this.layer=this.box=null;this.dragControl.destroy();this.dragControl=null;OpenLayers.Control.prototype.destroy.apply(this,arguments)},
2715 CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:"olHandlerBoxZoomBox",boxOffsets:null,initialize:function(a,b,c){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask})},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.dragHandler&&(this.dragHandler.destroy(),this.dragHandler=
2716 null)},setMap:function(a){OpenLayers.Handler.prototype.setMap.apply(this,arguments);this.dragHandler&&this.dragHandler.setMap(a)},startBox:function(a){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv("zoomBox",{x:-9999,y:-9999});this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE.Popup-1;this.map.viewPortDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.viewPortDiv,"olDrawBox")},moveBox:function(a){var b=this.dragHandler.start.x,
2717 c=this.dragHandler.start.y,d=Math.abs(b-a.x),e=Math.abs(c-a.y),f=this.getBoxOffsets();this.zoomBox.style.width=d+f.width+1+"px";this.zoomBox.style.height=e+f.height+1+"px";this.zoomBox.style.left=(a.x<b?b-d-f.left:b-f.left)+"px";this.zoomBox.style.top=(a.y<c?c-e-f.top:c-f.top)+"px"},endBox:function(a){var b;if(5<Math.abs(this.dragHandler.start.x-a.x)||5<Math.abs(this.dragHandler.start.y-a.y)){var c=this.dragHandler.start;b=Math.min(c.y,a.y);var d=Math.max(c.y,a.y),e=Math.min(c.x,a.x);a=Math.max(c.x,
2718 a.x);b=new OpenLayers.Bounds(e,d,a,b)}else b=this.dragHandler.start.clone();this.removeBox();this.callback("done",[b])},removeBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.boxOffsets=this.zoomBox=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDrawBox")},activate:function(){return OpenLayers.Handler.prototype.activate.apply(this,arguments)?(this.dragHandler.activate(),!0):!1},deactivate:function(){return OpenLayers.Handler.prototype.deactivate.apply(this,arguments)?
2719 (this.dragHandler.deactivate()&&this.zoomBox&&this.removeBox(),!0):!1},getBoxOffsets:function(){if(!this.boxOffsets){var a=document.createElement("div");a.style.position="absolute";a.style.border="1px solid black";a.style.width="3px";document.body.appendChild(a);var b=3==a.clientWidth;document.body.removeChild(a);var a=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width")),c=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width")),d=parseInt(OpenLayers.Element.getStyle(this.zoomBox,
2720 "border-top-width")),e=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"));this.boxOffsets={left:a,right:c,top:d,bottom:e,width:!1===b?a+c:0,height:!1===b?d+e:0}}return this.boxOffsets},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:!1,keyMask:null,alwaysZoom:!1,zoomOnClick:!0,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask})},zoomBox:function(a){if(a instanceof OpenLayers.Bounds){var b,c=a.getCenterPixel();if(this.out){b=Math.min(this.map.size.h/(a.bottom-a.top),this.map.size.w/(a.right-a.left));var d=this.map.getExtent(),e=this.map.getLonLatFromPixel(c),f=e.lon-d.getWidth()/
2721 2*b;a=e.lon+d.getWidth()/2*b;var g=e.lat-d.getHeight()/2*b;b=e.lat+d.getHeight()/2*b;b=new OpenLayers.Bounds(f,g,a,b)}else f=this.map.getLonLatFromPixel({x:a.left,y:a.bottom}),a=this.map.getLonLatFromPixel({x:a.right,y:a.top}),b=new OpenLayers.Bounds(f.lon,f.lat,a.lon,a.lat);f=this.map.getZoom();g=this.map.getSize();a=g.w/2;g=g.h/2;b=this.map.getZoomForExtent(b);d=this.map.getResolution();e=this.map.getResolutionForZoom(b);d==e?this.map.setCenter(this.map.getLonLatFromPixel(c)):this.map.zoomTo(b,
2722 {x:(d*c.x-e*a)/(d-e),y:(d*c.y-e*g)/(d-e)});f==this.map.getZoom()&&!0==this.alwaysZoom&&this.map.zoomTo(f+(this.out?-1:1))}else this.zoomOnClick&&(this.out?this.map.zoomTo(this.map.getZoom()-1,a):this.map.zoomTo(this.map.getZoom()+1,a))},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:!1,interval:0,documentDrag:!1,kinetic:null,enableKinetic:!0,kineticInterval:10,draw:function(){if(this.enableKinetic&&OpenLayers.Kinetic){var a={interval:this.kineticInterval};"object"===typeof this.enableKinetic&&(a=OpenLayers.Util.extend(a,this.enableKinetic));this.kinetic=new OpenLayers.Kinetic(a)}this.handler=new OpenLayers.Handler.Drag(this,{move:this.panMap,done:this.panMapDone,down:this.panMapStart},
2723 {interval:this.interval,documentDrag:this.documentDrag})},panMapStart:function(){this.kinetic&&this.kinetic.begin()},panMap:function(a){this.kinetic&&this.kinetic.update(a);this.panned=!0;this.map.pan(this.handler.last.x-a.x,this.handler.last.y-a.y,{dragging:!0,animate:!1})},panMapDone:function(a){if(this.panned){var b=null;this.kinetic&&(b=this.kinetic.end(a));this.map.pan(this.handler.last.x-a.x,this.handler.last.y-a.y,{dragging:!!b,animate:!1});if(b){var c=this;this.kinetic.move(b,function(a,b,
2724 f){c.map.pan(a,b,{dragging:!f,animate:!1})})}this.panned=!1}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Control.Navigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,pinchZoom:null,pinchZoomOptions:null,documentDrag:!1,zoomBox:null,zoomBoxEnabled:!0,zoomWheelEnabled:!0,mouseWheelOptions:null,handleRightClicks:!1,zoomBoxKeyMask:OpenLayers.Handler.MOD_SHIFT,autoActivate:!0,initialize:function(a){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments)},destroy:function(){this.deactivate();this.dragPan&&this.dragPan.destroy();this.dragPan=null;
2725 this.zoomBox&&this.zoomBox.destroy();this.zoomBox=null;this.pinchZoom&&this.pinchZoom.destroy();this.pinchZoom=null;OpenLayers.Control.prototype.destroy.apply(this,arguments)},activate:function(){this.dragPan.activate();this.zoomWheelEnabled&&this.handlers.wheel.activate();this.handlers.click.activate();this.zoomBoxEnabled&&this.zoomBox.activate();this.pinchZoom&&this.pinchZoom.activate();return OpenLayers.Control.prototype.activate.apply(this,arguments)},deactivate:function(){this.pinchZoom&&this.pinchZoom.deactivate();
2726 this.zoomBox.deactivate();this.dragPan.deactivate();this.handlers.click.deactivate();this.handlers.wheel.deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},draw:function(){this.handleRightClicks&&(this.map.viewPortDiv.oncontextmenu=OpenLayers.Function.False);this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.defaultClick,dblclick:this.defaultDblClick,dblrightclick:this.defaultDblRightClick},{"double":!0,stopDouble:!0});this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,
2727 documentDrag:this.documentDrag},this.dragPanOptions));this.zoomBox=new OpenLayers.Control.ZoomBox({map:this.map,keyMask:this.zoomBoxKeyMask});this.dragPan.draw();this.zoomBox.draw();this.handlers.wheel=new OpenLayers.Handler.MouseWheel(this,{up:this.wheelUp,down:this.wheelDown},OpenLayers.Util.extend(this.map.fractionalZoom?{}:{cumulative:!1,interval:50,maxDelta:6},this.mouseWheelOptions));OpenLayers.Control.PinchZoom&&(this.pinchZoom=new OpenLayers.Control.PinchZoom(OpenLayers.Util.extend({map:this.map},
2728 this.pinchZoomOptions)))},defaultClick:function(a){a.lastTouches&&2==a.lastTouches.length&&this.map.zoomOut()},defaultDblClick:function(a){this.map.zoomTo(this.map.zoom+1,a.xy)},defaultDblRightClick:function(a){this.map.zoomTo(this.map.zoom-1,a.xy)},wheelChange:function(a,b){this.map.fractionalZoom||(b=Math.round(b));var c=this.map.getZoom(),d;d=Math.max(c+b,0);d=Math.min(d,this.map.getNumZoomLevels());d!==c&&this.map.zoomTo(d,a.xy)},wheelUp:function(a,b){this.wheelChange(a,b||1)},wheelDown:function(a,
2729 b){this.wheelChange(a,b||-1)},disableZoomBox:function(){this.zoomBoxEnabled=!1;this.zoomBox.deactivate()},enableZoomBox:function(){this.zoomBoxEnabled=!0;this.active&&this.zoomBox.activate()},disableZoomWheel:function(){this.zoomWheelEnabled=!1;this.handlers.wheel.deactivate()},enableZoomWheel:function(){this.zoomWheelEnabled=!0;this.active&&this.handlers.wheel.activate()},CLASS_NAME:"OpenLayers.Control.Navigation"});OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,multi:!1,featureAdded:function(){},initialize:function(a,b,c){OpenLayers.Control.prototype.initialize.apply(this,[c]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(a,b){this.layer.events.triggerEvent("sketchmodified",{vertex:a,feature:b})},create:function(a,b){this.layer.events.triggerEvent("sketchstarted",{vertex:a,feature:b})}},this.callbacks);this.layer=a;this.handlerOptions=
2730 this.handlerOptions||{};this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{renderers:a.renderers,rendererOptions:a.rendererOptions});"multi"in this.handlerOptions||(this.handlerOptions.multi=this.multi);if(a=this.layer.styleMap&&this.layer.styleMap.styles.temporary)this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":a})});this.handler=new b(this,this.callbacks,this.handlerOptions)},
2731 drawFeature:function(a){a=new OpenLayers.Feature.Vector(a);!1!==this.layer.events.triggerEvent("sketchcomplete",{feature:a})&&(a.state=OpenLayers.State.INSERT,this.layer.addFeatures([a]),this.featureAdded(a),this.events.triggerEvent("featureadded",{feature:a}))},insertXY:function(a,b){this.handler&&this.handler.line&&this.handler.insertXY(a,b)},insertDeltaXY:function(a,b){this.handler&&this.handler.line&&this.handler.insertDeltaXY(a,b)},insertDirectionLength:function(a,b){this.handler&&this.handler.line&&
2732 this.handler.insertDirectionLength(a,b)},insertDeflectionLength:function(a,b){this.handler&&this.handler.line&&this.handler.insertDeflectionLength(a,b)},undo:function(){return this.handler.undo&&this.handler.undo()},redo:function(){return this.handler.redo&&this.handler.redo()},finishSketch:function(){this.handler.finishGeometry()},cancel:function(){this.handler.cancel()},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Handler.Polygon=OpenLayers.Class(OpenLayers.Handler.Path,{holeModifier:null,drawingHole:!1,polygon:null,createFeature:function(a){a=this.layer.getLonLatFromViewPortPx(a);a=new OpenLayers.Geometry.Point(a.lon,a.lat);this.point=new OpenLayers.Feature.Vector(a);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LinearRing([this.point.geometry]));this.polygon=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([this.line.geometry]));this.callback("create",[this.point.geometry,
2733 this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.polygon,this.point],{silent:!0})},addPoint:function(a){if(!this.drawingHole&&this.holeModifier&&this.evt&&this.evt[this.holeModifier])for(var b=this.point.geometry,c=this.control.layer.features,d,e=c.length-1;0<=e;--e)if(d=c[e].geometry,(d instanceof OpenLayers.Geometry.Polygon||d instanceof OpenLayers.Geometry.MultiPolygon)&&d.intersects(b)){b=c[e];this.control.layer.removeFeatures([b],{silent:!0});this.control.layer.events.registerPriority("sketchcomplete",
2734 this,this.finalizeInteriorRing);this.control.layer.events.registerPriority("sketchmodified",this,this.enforceTopology);b.geometry.addComponent(this.line.geometry);this.polygon=b;this.drawingHole=!0;break}OpenLayers.Handler.Path.prototype.addPoint.apply(this,arguments)},getCurrentPointIndex:function(){return this.line.geometry.components.length-2},enforceTopology:function(a){a=a.vertex;var b=this.line.geometry.components;this.polygon.geometry.intersects(a)||(b=b[b.length-3],a.x=b.x,a.y=b.y)},finishGeometry:function(){this.line.geometry.removeComponent(this.line.geometry.components[this.line.geometry.components.length-
2735 2]);this.removePoint();this.finalize()},finalizeInteriorRing:function(){var a=this.line.geometry,b=0!==a.getArea();if(b){for(var c=this.polygon.geometry.components,d=c.length-2;0<=d;--d)if(a.intersects(c[d])){b=!1;break}if(b)a:for(d=c.length-2;0<d;--d)for(var e=c[d].components,f=0,g=e.length;f<g;++f)if(a.containsPoint(e[f])){b=!1;break a}}b?this.polygon.state!==OpenLayers.State.INSERT&&(this.polygon.state=OpenLayers.State.UPDATE):this.polygon.geometry.removeComponent(a);this.restoreFeature();return!1},
2736 cancel:function(){this.drawingHole&&(this.polygon.geometry.removeComponent(this.line.geometry),this.restoreFeature(!0));return OpenLayers.Handler.Path.prototype.cancel.apply(this,arguments)},restoreFeature:function(a){this.control.layer.events.unregister("sketchcomplete",this,this.finalizeInteriorRing);this.control.layer.events.unregister("sketchmodified",this,this.enforceTopology);this.layer.removeFeatures([this.polygon],{silent:!0});this.control.layer.addFeatures([this.polygon],{silent:!0});this.drawingHole=
2737 !1;a||this.control.layer.events.triggerEvent("sketchcomplete",{feature:this.polygon})},destroyFeature:function(a){OpenLayers.Handler.Path.prototype.destroyFeature.call(this,a);this.polygon=null},drawFeature:function(){this.layer.drawFeature(this.polygon,this.style);this.layer.drawFeature(this.point,this.style)},getSketch:function(){return this.polygon},getGeometry:function(){var a=this.polygon&&this.polygon.geometry;a&&this.multi&&(a=new OpenLayers.Geometry.MultiPolygon([a]));return a},CLASS_NAME:"OpenLayers.Handler.Polygon"});OpenLayers.Control.EditingToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{citeCompliant:!1,initialize:function(a,b){OpenLayers.Control.Panel.prototype.initialize.apply(this,[b]);this.addControls([new OpenLayers.Control.Navigation]);var c=[new OpenLayers.Control.DrawFeature(a,OpenLayers.Handler.Point,{displayClass:"olControlDrawFeaturePoint",handlerOptions:{citeCompliant:this.citeCompliant}}),new OpenLayers.Control.DrawFeature(a,OpenLayers.Handler.Path,{displayClass:"olControlDrawFeaturePath",handlerOptions:{citeCompliant:this.citeCompliant}}),
2738 new OpenLayers.Control.DrawFeature(a,OpenLayers.Handler.Polygon,{displayClass:"olControlDrawFeaturePolygon",handlerOptions:{citeCompliant:this.citeCompliant}})];this.addControls(c)},draw:function(){var a=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);null===this.defaultControl&&(this.defaultControl=this.controls[0]);return a},CLASS_NAME:"OpenLayers.Control.EditingToolbar"});OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,activate:function(){var a=OpenLayers.Strategy.prototype.activate.call(this);a&&(this.layer.events.on({moveend:this.update,refresh:this.update,visibilitychanged:this.update,scope:this}),this.update());return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&this.layer.events.un({moveend:this.update,refresh:this.update,visibilitychanged:this.update,
2739 scope:this});return a},update:function(a){var b=this.getMapBounds();null!==b&&(a&&a.force||this.layer.visibility&&this.layer.calculateInRange()&&this.invalidBounds(b))&&(this.calculateBounds(b),this.resolution=this.layer.map.getResolution(),this.triggerRead(a))},getMapBounds:function(){if(null===this.layer.map)return null;var a=this.layer.map.getExtent();a&&!this.layer.projection.equals(this.layer.map.getProjectionObject())&&(a=a.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection));
2740 return a},invalidBounds:function(a){a||(a=this.getMapBounds());a=!this.bounds||!this.bounds.containsBounds(a);!a&&this.resFactor&&(a=this.resolution/this.layer.map.getResolution(),a=a>=this.resFactor||a<=1/this.resFactor);return a},calculateBounds:function(a){a||(a=this.getMapBounds());var b=a.getCenterLonLat(),c=a.getWidth()*this.ratio;a=a.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(b.lon-c/2,b.lat-a/2,b.lon+c/2,b.lat+a/2)},triggerRead:function(a){!this.response||a&&!0===a.noAbort||
2741 (this.layer.protocol.abort(this.response),this.layer.events.triggerEvent("loadend"));var b={filter:this.createFilter()};this.layer.events.triggerEvent("loadstart",b);this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:b.filter,callback:this.merge,scope:this},a))},createFilter:function(){var a=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});this.layer.filter&&(a=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,
2742 filters:[this.layer.filter,a]}));return a},merge:function(a){this.layer.destroyFeatures();if(a.success()){var b=a.features;if(b&&0<b.length){var c=this.layer.projection,d=this.layer.map.getProjectionObject();if(!d.equals(c))for(var e,f=0,g=b.length;f<g;++f)(e=b[f].geometry)&&e.transform(c,d);this.layer.addFeatures(b)}}else this.bounds=null;this.response=null;this.layer.events.triggerEvent("loadend",{response:a})},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Layer.WorldWind=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{},isBaseLayer:!0,lzd:null,zoomLevels:null,initialize:function(a,b,c,d,e,f){this.lzd=c;this.zoomLevels=d;c=[];c.push(a,b,e,f);OpenLayers.Layer.Grid.prototype.initialize.apply(this,c);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS)},getZoom:function(){var a=this.map.getZoom();this.map.getMaxExtent();return a-=Math.log(this.maxResolution/(this.lzd/512))/Math.log(2)},getURL:function(a){a=this.adjustBounds(a);
2743 var b=this.getZoom(),c=this.map.getMaxExtent(),d=this.lzd/Math.pow(2,this.getZoom()),e=Math.floor((a.left-c.left)/d);a=Math.floor((a.bottom-c.bottom)/d);return this.map.getResolution()<=this.lzd/512&&this.getZoom()<=this.zoomLevels?this.getFullRequestString({L:b,X:e,Y:a}):OpenLayers.Util.getImageLocation("blank.gif")},CLASS_NAME:"OpenLayers.Layer.WorldWind"});OpenLayers.Protocol.CSW=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Protocol.CSW.DEFAULTS);var b=OpenLayers.Protocol.CSW["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported CSW version: "+a.version;return new b(a)};OpenLayers.Protocol.CSW.DEFAULTS={version:"2.0.2"};OpenLayers.Format.WMTSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",yx:{"urn:ogc:def:crs:EPSG::4326":!0},createLayer:function(a,b){if(!("layer"in b))throw Error("Missing property 'layer' in configuration.");for(var c=a.contents,d,e=0,f=c.layers.length;e<f;++e)if(c.layers[e].identifier===b.layer){d=c.layers[e];break}if(!d)throw Error("Layer not found");var g=b.format;!g&&(d.formats&&d.formats.length)&&(g=d.formats[0]);var h;b.matrixSet?h=c.tileMatrixSets[b.matrixSet]:
2744 1<=d.tileMatrixSetLinks.length&&(h=c.tileMatrixSets[d.tileMatrixSetLinks[0].tileMatrixSet]);if(!h)throw Error("matrixSet not found");for(var k,e=0,f=d.styles.length;e<f&&(k=d.styles[e],!k.isDefault);++e);c=b.requestEncoding;if(!c&&(c="KVP",a.operationsMetadata.GetTile.dcp.http)){var l=a.operationsMetadata.GetTile.dcp.http;l.get[0].constraints&&(l=l.get[0].constraints.GetEncoding.allowedValues,l.KVP||!l.REST&&!l.RESTful||(c="REST"))}var l=[],m=b.params||{};delete b.params;for(var n=0,p=d.dimensions.length;n<
2745 p;n++){var q=d.dimensions[n];l.push(q.identifier);m.hasOwnProperty(q.identifier)||(m[q.identifier]=q["default"])}var n=b.projection||h.supportedCRS.replace(/urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/,"$1:$3"),p=b.units||("EPSG:4326"===n?"degrees":"m"),q=[],r;for(r in h.matrixIds)h.matrixIds.hasOwnProperty(r)&&q.push(2.8E-4*h.matrixIds[r].scaleDenominator/OpenLayers.METERS_PER_INCH/OpenLayers.INCHES_PER_UNIT[p]);if("REST"===c&&d.resourceUrls){r=[];for(var f=0,s=d.resourceUrls.length;f<s;++f)e=d.resourceUrls[f],
2746 e.format===g&&"tile"===e.resourceType&&r.push(e.template)}else{s=a.operationsMetadata.GetTile.dcp.http.get;r=[];for(var t,e=0,f=s.length;e<f;e++)t=s[e].constraints,(!t||t&&t.GetEncoding.allowedValues[c])&&r.push(s[e].url)}return new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults(b,{url:r,requestEncoding:c,name:d.title,style:k.identifier,format:g,matrixIds:h.matrixIds,matrixSet:h.identifier,projection:n,units:p,resolutions:!1===b.isBaseLayer?void 0:q,serverResolutions:q,tileFullExtent:h.bounds,
2747 dimensions:l,params:m}))},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities"});OpenLayers.Layer.Google.v3={DEFAULTS:{sphericalMercator:!0,projection:"EPSG:900913"},animationEnabled:!0,loadMapObject:function(){this.type||(this.type=google.maps.MapTypeId.ROADMAP);var a,b=OpenLayers.Layer.Google.cache[this.map.id];b?(a=b.mapObject,++b.count):(a=this.map.getCenter(),b=document.createElement("div"),b.className="olForeignContainer",b.style.width="100%",b.style.height="100%",a=new google.maps.Map(b,{center:a?new google.maps.LatLng(a.lat,a.lon):new google.maps.LatLng(0,0),zoom:this.map.getZoom()||
2748 0,mapTypeId:this.type,disableDefaultUI:!0,keyboardShortcuts:!1,draggable:!1,disableDoubleClickZoom:!0,scrollwheel:!1,streetViewControl:!1}),b=document.createElement("div"),b.style.width="100%",b.style.height="100%",a.controls[google.maps.ControlPosition.TOP_LEFT].push(b),b={googleControl:b,mapObject:a,count:1},OpenLayers.Layer.Google.cache[this.map.id]=b);this.mapObject=a;this.setGMapVisibility(this.visibility)},onMapResize:function(){this.visibility&&google.maps.event.trigger(this.mapObject,"resize")},
2749 setGMapVisibility:function(a){var b=OpenLayers.Layer.Google.cache[this.map.id],c=this.map;if(b){for(var d=this.type,e=c.layers,f,g=e.length-1;0<=g;--g)if(f=e[g],f instanceof OpenLayers.Layer.Google&&!0===f.visibility&&!0===f.inRange){d=f.type;a=!0;break}e=this.mapObject.getDiv();if(!0===a){if(e.parentNode!==c.div)if(b.rendered)c.div.appendChild(e),b.googleControl.appendChild(c.viewPortDiv),google.maps.event.trigger(this.mapObject,"resize");else{var h=this;google.maps.event.addListenerOnce(this.mapObject,
2750 "tilesloaded",function(){b.rendered=!0;h.setGMapVisibility(h.getVisibility());h.moveTo(h.map.getCenter())})}this.mapObject.setMapTypeId(d)}else b.googleControl.hasChildNodes()&&(c.div.appendChild(c.viewPortDiv),c.div.removeChild(e))}},getMapContainer:function(){return this.mapObject.getDiv()},getMapObjectBoundsFromOLBounds:function(a){var b=null;null!=a&&(b=this.sphericalMercator?this.inverseMercator(a.bottom,a.left):new OpenLayers.LonLat(a.bottom,a.left),a=this.sphericalMercator?this.inverseMercator(a.top,
2751 a.right):new OpenLayers.LonLat(a.top,a.right),b=new google.maps.LatLngBounds(new google.maps.LatLng(b.lat,b.lon),new google.maps.LatLng(a.lat,a.lon)));return b},getMapObjectLonLatFromMapObjectPixel:function(a){var b=this.map.getSize(),c=this.getLongitudeFromMapObjectLonLat(this.mapObject.center),d=this.getLatitudeFromMapObjectLonLat(this.mapObject.center),e=this.map.getResolution();a=new OpenLayers.LonLat(c+(a.x-b.w/2)*e,d-(a.y-b.h/2)*e);this.wrapDateLine&&(a=a.wrapDateLine(this.maxExtent));return this.getMapObjectLonLatFromLonLat(a.lon,
2752 a.lat)},getMapObjectPixelFromMapObjectLonLat:function(a){var b=this.getLongitudeFromMapObjectLonLat(a);a=this.getLatitudeFromMapObjectLonLat(a);var c=this.map.getResolution(),d=this.map.getExtent();return this.getMapObjectPixelFromXY(1/c*(b-d.left),1/c*(d.top-a))},setMapObjectCenter:function(a,b){if(!1===this.animationEnabled&&b!=this.mapObject.zoom){var c=this.getMapContainer();google.maps.event.addListenerOnce(this.mapObject,"idle",function(){c.style.visibility=""});c.style.visibility="hidden"}this.mapObject.setOptions({center:a,
2753 zoom:b})},getMapObjectZoomFromMapObjectBounds:function(a){return this.mapObject.getBoundsZoomLevel(a)},getMapObjectLonLatFromLonLat:function(a,b){var c;this.sphericalMercator?(c=this.inverseMercator(a,b),c=new google.maps.LatLng(c.lat,c.lon)):c=new google.maps.LatLng(b,a);return c},getMapObjectPixelFromXY:function(a,b){return new google.maps.Point(a,b)}};OpenLayers.Format.WPSDescribeProcess=OpenLayers.Class(OpenLayers.Format.XML,{VERSION:"1.0.0",namespaces:{wps:"http://www.opengis.net/wps/1.0.0",ows:"http://www.opengis.net/ows/1.1",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",defaultPrefix:"wps",regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,
2754 [a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},readers:{wps:{ProcessDescriptions:function(a,b){b.processDescriptions={};this.readChildNodes(a,b.processDescriptions)},ProcessDescription:function(a,b){var c={processVersion:this.getAttributeNS(a,this.namespaces.wps,"processVersion"),statusSupported:"true"===a.getAttribute("statusSupported"),storeSupported:"true"===a.getAttribute("storeSupported")};this.readChildNodes(a,c);b[c.identifier]=c},DataInputs:function(a,
2755 b){b.dataInputs=[];this.readChildNodes(a,b.dataInputs)},ProcessOutputs:function(a,b){b.processOutputs=[];this.readChildNodes(a,b.processOutputs)},Output:function(a,b){var c={};this.readChildNodes(a,c);b.push(c)},ComplexOutput:function(a,b){b.complexOutput={};this.readChildNodes(a,b.complexOutput)},LiteralOutput:function(a,b){b.literalOutput={};this.readChildNodes(a,b.literalOutput)},Input:function(a,b){var c={maxOccurs:parseInt(a.getAttribute("maxOccurs")),minOccurs:parseInt(a.getAttribute("minOccurs"))};
2756 this.readChildNodes(a,c);b.push(c)},BoundingBoxData:function(a,b){b.boundingBoxData={};this.readChildNodes(a,b.boundingBoxData)},CRS:function(a,b){b.CRSs||(b.CRSs={});b.CRSs[this.getChildValue(a)]=!0},LiteralData:function(a,b){b.literalData={};this.readChildNodes(a,b.literalData)},ComplexData:function(a,b){b.complexData={};this.readChildNodes(a,b.complexData)},Default:function(a,b){b["default"]={};this.readChildNodes(a,b["default"])},Supported:function(a,b){b.supported={};this.readChildNodes(a,b.supported)},
2757 Format:function(a,b){var c={};this.readChildNodes(a,c);b.formats||(b.formats={});b.formats[c.mimeType]=!0},MimeType:function(a,b){b.mimeType=this.getChildValue(a)}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WPSDescribeProcess"});OpenLayers.Format.WKT=OpenLayers.Class(OpenLayers.Format,{initialize:function(a){this.regExes={typeStr:/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,spaces:/\s+/,parenComma:/\)\s*,\s*\(/,doubleParenComma:/\)\s*\)\s*,\s*\(\s*\(/,trimParens:/^\s*\(?(.*?)\)?\s*$/};OpenLayers.Format.prototype.initialize.apply(this,[a])},read:function(a){var b,c;a=a.replace(/[\n\r]/g," ");if(c=this.regExes.typeStr.exec(a))if(a=c[1].toLowerCase(),c=c[2],this.parse[a]&&(b=this.parse[a].apply(this,[c])),this.internalProjection&&this.externalProjection)if(b&&
2758 "OpenLayers.Feature.Vector"==b.CLASS_NAME)b.geometry.transform(this.externalProjection,this.internalProjection);else if(b&&"geometrycollection"!=a&&"object"==typeof b)for(a=0,c=b.length;a<c;a++)b[a].geometry.transform(this.externalProjection,this.internalProjection);return b},write:function(a){var b,c;a.constructor==Array?c=!0:(a=[a],c=!1);var d=[];c&&d.push("GEOMETRYCOLLECTION(");for(var e=0,f=a.length;e<f;++e)c&&0<e&&d.push(","),b=a[e].geometry,d.push(this.extractGeometry(b));c&&d.push(")");return d.join("")},
2759 extractGeometry:function(a){var b=a.CLASS_NAME.split(".")[2].toLowerCase();if(!this.extract[b])return null;this.internalProjection&&this.externalProjection&&(a=a.clone(),a.transform(this.internalProjection,this.externalProjection));return("collection"==b?"GEOMETRYCOLLECTION":b.toUpperCase())+"("+this.extract[b].apply(this,[a])+")"},extract:{point:function(a){return a.x+" "+a.y},multipoint:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push("("+this.extract.point.apply(this,[a.components[c]])+
2760 ")");return b.join(",")},linestring:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extract.point.apply(this,[a.components[c]]));return b.join(",")},multilinestring:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push("("+this.extract.linestring.apply(this,[a.components[c]])+")");return b.join(",")},polygon:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push("("+this.extract.linestring.apply(this,[a.components[c]])+")");return b.join(",")},multipolygon:function(a){for(var b=
2761 [],c=0,d=a.components.length;c<d;++c)b.push("("+this.extract.polygon.apply(this,[a.components[c]])+")");return b.join(",")},collection:function(a){for(var b=[],c=0,d=a.components.length;c<d;++c)b.push(this.extractGeometry.apply(this,[a.components[c]]));return b.join(",")}},parse:{point:function(a){a=OpenLayers.String.trim(a).split(this.regExes.spaces);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(a[0],a[1]))},multipoint:function(a){for(var b=OpenLayers.String.trim(a).split(","),
2762 c=[],d=0,e=b.length;d<e;++d)a=b[d].replace(this.regExes.trimParens,"$1"),c.push(this.parse.point.apply(this,[a]).geometry);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPoint(c))},linestring:function(a){a=OpenLayers.String.trim(a).split(",");for(var b=[],c=0,d=a.length;c<d;++c)b.push(this.parse.point.apply(this,[a[c]]).geometry);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(b))},multilinestring:function(a){for(var b=OpenLayers.String.trim(a).split(this.regExes.parenComma),
2763 c=[],d=0,e=b.length;d<e;++d)a=b[d].replace(this.regExes.trimParens,"$1"),c.push(this.parse.linestring.apply(this,[a]).geometry);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiLineString(c))},polygon:function(a){var b;a=OpenLayers.String.trim(a).split(this.regExes.parenComma);for(var c=[],d=0,e=a.length;d<e;++d)b=a[d].replace(this.regExes.trimParens,"$1"),b=this.parse.linestring.apply(this,[b]).geometry,b=new OpenLayers.Geometry.LinearRing(b.components),c.push(b);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon(c))},
2764 multipolygon:function(a){for(var b=OpenLayers.String.trim(a).split(this.regExes.doubleParenComma),c=[],d=0,e=b.length;d<e;++d)a=b[d].replace(this.regExes.trimParens,"$1"),c.push(this.parse.polygon.apply(this,[a]).geometry);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(c))},geometrycollection:function(a){a=a.replace(/,\s*([A-Za-z])/g,"|$1");a=OpenLayers.String.trim(a).split("|");for(var b=[],c=0,d=a.length;c<d;++c)b.push(OpenLayers.Format.WKT.prototype.read.apply(this,[a[c]]));
2765 return b}},CLASS_NAME:"OpenLayers.Format.WKT"});OpenLayers.WPSProcess=OpenLayers.Class({client:null,server:null,identifier:null,description:null,localWPS:"http://geoserver/wps",formats:null,chained:0,executeCallbacks:null,initialize:function(a){OpenLayers.Util.extend(this,a);this.executeCallbacks=[];this.formats={"application/wkt":new OpenLayers.Format.WKT,"application/json":new OpenLayers.Format.GeoJSON}},describe:function(a){a=a||{};if(!this.description)this.client.describeProcess(this.server,this.identifier,function(b){this.description||this.parseDescription(b);
2766 a.callback&&a.callback.call(a.scope,this.description)},this);else if(a.callback){var b=this.description;window.setTimeout(function(){a.callback.call(a.scope,b)},0)}},configure:function(a){this.describe({callback:function(){var b=this.description,c=a.inputs,d,e,f;e=0;for(f=b.dataInputs.length;e<f;++e)d=b.dataInputs[e],this.setInputData(d,c[d.identifier]);a.callback&&a.callback.call(a.scope)},scope:this});return this},execute:function(a){this.configure({inputs:a.inputs,callback:function(){var b=this,
2767 c=this.getOutputIndex(b.description.processOutputs,a.output);b.setResponseForm({outputIndex:c});(function e(){OpenLayers.Util.removeItem(b.executeCallbacks,e);0!==b.chained?b.executeCallbacks.push(e):OpenLayers.Request.POST({url:b.client.servers[b.server].url,data:(new OpenLayers.Format.WPSExecute).write(b.description),success:function(e){var g=b.findMimeType(b.description.processOutputs[c].complexOutput.supported.formats);e=b.formats[g].read(e.responseText);e instanceof OpenLayers.Feature.Vector&&
2768 (e=[e]);a.success&&(g={},g[a.output||"result"]=e,a.success.call(a.scope,g))},scope:b})})()},scope:this})},output:function(a){return new OpenLayers.WPSProcess.ChainLink({process:this,output:a})},parseDescription:function(a){a=this.client.servers[this.server];this.description=(new OpenLayers.Format.WPSDescribeProcess).read(a.processDescription[this.identifier]).processDescriptions[this.identifier]},setInputData:function(a,b){delete a.data;delete a.reference;if(b instanceof OpenLayers.WPSProcess.ChainLink)++this.chained,
2769 a.reference={method:"POST",href:b.process.server===this.server?this.localWPS:this.client.servers[b.process.server].url},b.process.describe({callback:function(){--this.chained;this.chainProcess(a,b)},scope:this});else{a.data={};var c=a.complexData;c?(c=this.findMimeType(c.supported.formats),a.data.complexData={mimeType:c,value:this.formats[c].write(this.toFeatures(b))}):a.data.literalData={value:b}}},setResponseForm:function(a){a=a||{};var b=this.description.processOutputs[a.outputIndex||0];this.description.responseForm=
2770 {rawDataOutput:{identifier:b.identifier,mimeType:this.findMimeType(b.complexOutput.supported.formats,a.supportedFormats)}}},getOutputIndex:function(a,b){var c;if(b)for(var d=a.length-1;0<=d;--d){if(a[d].identifier===b){c=d;break}}else c=0;return c},chainProcess:function(a,b){var c=this.getOutputIndex(b.process.description.processOutputs,b.output);a.reference.mimeType=this.findMimeType(a.complexData.supported.formats,b.process.description.processOutputs[c].complexOutput.supported.formats);var d={};
2771 d[a.reference.mimeType]=!0;b.process.setResponseForm({outputIndex:c,supportedFormats:d});for(a.reference.body=b.process.description;0<this.executeCallbacks.length;)this.executeCallbacks[0]()},toFeatures:function(a){var b=OpenLayers.Util.isArray(a);b||(a=[a]);for(var c=Array(a.length),d,e=0,f=a.length;e<f;++e)d=a[e],c[e]=d instanceof OpenLayers.Feature.Vector?d:new OpenLayers.Feature.Vector(d);return b?c:c[0]},findMimeType:function(a,b){b=b||this.formats;for(var c in a)if(c in b)return c},CLASS_NAME:"OpenLayers.WPSProcess"});
2772 OpenLayers.WPSProcess.ChainLink=OpenLayers.Class({process:null,output:null,initialize:function(a){OpenLayers.Util.extend(this,a)},CLASS_NAME:"OpenLayers.WPSProcess.ChainLink"});OpenLayers.WPSClient=OpenLayers.Class({servers:null,version:"1.0.0",lazy:!1,events:null,initialize:function(a){OpenLayers.Util.extend(this,a);this.events=new OpenLayers.Events(this);this.servers={};for(var b in a.servers)this.servers[b]="string"==typeof a.servers[b]?{url:a.servers[b],version:this.version,processDescription:{}}:a.servers[b]},execute:function(a){this.getProcess(a.server,a.process).execute({inputs:a.inputs,success:a.success,scope:a.scope})},getProcess:function(a,b){var c=new OpenLayers.WPSProcess({client:this,
2773 server:a,identifier:b});this.lazy||c.describe();return c},describeProcess:function(a,b,c,d){var e=this.servers[a];e.processDescription[b]?window.setTimeout(function(){c.call(d,e.processDescription[b])},0):b in e.processDescription?this.events.register("describeprocess",this,function g(a){a.identifier===b&&(this.events.unregister("describeprocess",this,g),c.call(d,a.raw))}):(e.processDescription[b]=null,OpenLayers.Request.GET({url:e.url,params:{SERVICE:"WPS",VERSION:e.version,REQUEST:"DescribeProcess",
2774 IDENTIFIER:b},success:function(a){e.processDescription[b]=a.responseText;this.events.triggerEvent("describeprocess",{identifier:b,raw:a.responseText})},scope:this}))},destroy:function(){this.events.destroy();this.servers=this.events=null},CLASS_NAME:"OpenLayers.WPSClient"});OpenLayers.Format.CSWGetRecords.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{csw:"http://www.opengis.net/cat/csw/2.0.2",dc:"http://purl.org/dc/elements/1.1/",dct:"http://purl.org/dc/terms/",gmd:"http://www.isotc211.org/2005/gmd",geonet:"http://www.fao.org/geonetwork",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
2775 requestId:null,resultType:null,outputFormat:null,outputSchema:null,startPosition:null,maxRecords:null,DistributedSearch:null,ResponseHandler:null,Query:null,regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},
2776 readers:{csw:{GetRecordsResponse:function(a,b){b.records=[];this.readChildNodes(a,b);var c=this.getAttributeNS(a,"","version");""!=c&&(b.version=c)},RequestId:function(a,b){b.RequestId=this.getChildValue(a)},SearchStatus:function(a,b){b.SearchStatus={};var c=this.getAttributeNS(a,"","timestamp");""!=c&&(b.SearchStatus.timestamp=c)},SearchResults:function(a,b){this.readChildNodes(a,b);for(var c=a.attributes,d={},e=0,f=c.length;e<f;++e)d[c[e].name]="numberOfRecordsMatched"==c[e].name||"numberOfRecordsReturned"==
2777 c[e].name||"nextRecord"==c[e].name?parseInt(c[e].nodeValue):c[e].nodeValue;b.SearchResults=d},SummaryRecord:function(a,b){var c={type:"SummaryRecord"};this.readChildNodes(a,c);b.records.push(c)},BriefRecord:function(a,b){var c={type:"BriefRecord"};this.readChildNodes(a,c);b.records.push(c)},DCMIRecord:function(a,b){var c={type:"DCMIRecord"};this.readChildNodes(a,c);b.records.push(c)},Record:function(a,b){var c={type:"Record"};this.readChildNodes(a,c);b.records.push(c)},"*":function(a,b){var c=a.localName||
2778 a.nodeName.split(":").pop();b[c]=this.getChildValue(a)}},geonet:{info:function(a,b){var c={};this.readChildNodes(a,c);b.gninfo=c}},dc:{"*":function(a,b){var c=a.localName||a.nodeName.split(":").pop();OpenLayers.Util.isArray(b[c])||(b[c]=[]);for(var d={},e=a.attributes,f=0,g=e.length;f<g;++f)d[e[f].name]=e[f].nodeValue;d.value=this.getChildValue(a);""!=d.value&&b[c].push(d)}},dct:{"*":function(a,b){var c=a.localName||a.nodeName.split(":").pop();OpenLayers.Util.isArray(b[c])||(b[c]=[]);b[c].push(this.getChildValue(a))}},
2779 ows:OpenLayers.Util.applyDefaults({BoundingBox:function(a,b){b.bounds&&(b.BoundingBox=[{crs:b.projection,value:[b.bounds.left,b.bounds.bottom,b.bounds.right,b.bounds.top]}],delete b.projection,delete b.bounds);OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows.BoundingBox.apply(this,arguments)}},OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows)},write:function(a){a=this.writeNode("csw:GetRecords",a);a.setAttribute("xmlns:gmd",this.namespaces.gmd);return OpenLayers.Format.XML.prototype.write.apply(this,
2780 [a])},writers:{csw:{GetRecords:function(a){a||(a={});var b=this.createElementNSPlus("csw:GetRecords",{attributes:{service:"CSW",version:this.version,requestId:a.requestId||this.requestId,resultType:a.resultType||this.resultType,outputFormat:a.outputFormat||this.outputFormat,outputSchema:a.outputSchema||this.outputSchema,startPosition:a.startPosition||this.startPosition,maxRecords:a.maxRecords||this.maxRecords}});(a.DistributedSearch||this.DistributedSearch)&&this.writeNode("csw:DistributedSearch",
2781 a.DistributedSearch||this.DistributedSearch,b);var c=a.ResponseHandler||this.ResponseHandler;if(OpenLayers.Util.isArray(c)&&0<c.length)for(var d=0,e=c.length;d<e;d++)this.writeNode("csw:ResponseHandler",c[d],b);this.writeNode("Query",a.Query||this.Query,b);return b},DistributedSearch:function(a){return this.createElementNSPlus("csw:DistributedSearch",{attributes:{hopCount:a.hopCount}})},ResponseHandler:function(a){return this.createElementNSPlus("csw:ResponseHandler",{value:a.value})},Query:function(a){a||
2782 (a={});var b=this.createElementNSPlus("csw:Query",{attributes:{typeNames:a.typeNames||"csw:Record"}}),c=a.ElementName;if(OpenLayers.Util.isArray(c)&&0<c.length)for(var d=0,e=c.length;d<e;d++)this.writeNode("csw:ElementName",c[d],b);else this.writeNode("csw:ElementSetName",a.ElementSetName||{value:"summary"},b);a.Constraint&&this.writeNode("csw:Constraint",a.Constraint,b);a.SortBy&&this.writeNode("ogc:SortBy",a.SortBy,b);return b},ElementName:function(a){return this.createElementNSPlus("csw:ElementName",
2783 {value:a.value})},ElementSetName:function(a){return this.createElementNSPlus("csw:ElementSetName",{attributes:{typeNames:a.typeNames},value:a.value})},Constraint:function(a){var b=this.createElementNSPlus("csw:Constraint",{attributes:{version:a.version}});if(a.Filter){var c=new OpenLayers.Format.Filter({version:a.version});b.appendChild(c.write(a.Filter))}else a.CqlText&&(a=this.createElementNSPlus("CqlText",{value:a.CqlText.value}),b.appendChild(a));return b}},ogc:OpenLayers.Format.Filter.v1_1_0.prototype.writers.ogc},
2784 CLASS_NAME:"OpenLayers.Format.CSWGetRecords.v2_0_2"});/*
2785 Apache 2
2786
2787 Contains portions of Rico <http://openrico.org/>
2788
2789 Copyright 2005 Sabre Airline Solutions
2790
2791 Licensed under the Apache License, Version 2.0 (the "License"); you
2792 may not use this file except in compliance with the License. You
2793 may obtain a copy of the License at
2794
2795 http://www.apache.org/licenses/LICENSE-2.0
2796
2797 Unless required by applicable law or agreed to in writing, software
2798 distributed under the License is distributed on an "AS IS" BASIS,
2799 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
2800 implied. See the License for the specific language governing
2801 permissions and limitations under the License.
2802 */
2803 OpenLayers.Marker.Box=OpenLayers.Class(OpenLayers.Marker,{bounds:null,div:null,initialize:function(a,b,c){this.bounds=a;this.div=OpenLayers.Util.createDiv();this.div.style.overflow="hidden";this.events=new OpenLayers.Events(this,this.div);this.setBorder(b,c)},destroy:function(){this.div=this.bounds=null;OpenLayers.Marker.prototype.destroy.apply(this,arguments)},setBorder:function(a,b){a||(a="red");b||(b=2);this.div.style.border=b+"px solid "+a},draw:function(a,b){OpenLayers.Util.modifyDOMElement(this.div,
2804 null,a,b);return this.div},onScreen:function(){var a=!1;this.map&&(a=this.map.getExtent().containsBounds(this.bounds,!0,!0));return a},display:function(a){this.div.style.display=a?"":"none"},CLASS_NAME:"OpenLayers.Marker.Box"});OpenLayers.Format.Text=OpenLayers.Class(OpenLayers.Format,{defaultStyle:null,extractStyles:!0,initialize:function(a){a=a||{};!1!==a.extractStyles&&(a.defaultStyle={externalGraphic:OpenLayers.Util.getImageLocation("marker.png"),graphicWidth:21,graphicHeight:25,graphicXOffset:-10.5,graphicYOffset:-12.5});OpenLayers.Format.prototype.initialize.apply(this,[a])},read:function(a){a=a.split("\n");for(var b,c=[],d=0;d<a.length-1;d++){var e=a[d].replace(/^\s*/,"").replace(/\s*$/,"");if("#"!=e.charAt(0))if(b){for(var e=
2805 e.split("\t"),f=new OpenLayers.Geometry.Point(0,0),g={},h=this.defaultStyle?OpenLayers.Util.applyDefaults({},this.defaultStyle):null,k=!1,l=0;l<e.length;l++)if(e[l])if("point"==b[l])k=e[l].split(","),f.y=parseFloat(k[0]),f.x=parseFloat(k[1]),k=!0;else if("lat"==b[l])f.y=parseFloat(e[l]),k=!0;else if("lon"==b[l])f.x=parseFloat(e[l]),k=!0;else if("title"==b[l])g.title=e[l];else if("image"==b[l]||"icon"==b[l]&&h)h.externalGraphic=e[l];else if("iconSize"==b[l]&&h){var m=e[l].split(",");h.graphicWidth=
2806 parseFloat(m[0]);h.graphicHeight=parseFloat(m[1])}else"iconOffset"==b[l]&&h?(m=e[l].split(","),h.graphicXOffset=parseFloat(m[0]),h.graphicYOffset=parseFloat(m[1])):"description"==b[l]?g.description=e[l]:"overflow"==b[l]?g.overflow=e[l]:g[b[l]]=e[l];k&&(this.internalProjection&&this.externalProjection&&f.transform(this.externalProjection,this.internalProjection),e=new OpenLayers.Feature.Vector(f,g,h),c.push(e))}else b=e.split("\t")}return c},CLASS_NAME:"OpenLayers.Format.Text"});OpenLayers.Layer.Text=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,initialize:function(a,b){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);this.features=[]},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null},loadText:function(){this.loaded||null==this.location||(this.events.triggerEvent("loadstart"),OpenLayers.Request.GET({url:this.location,
2807 success:this.parseData,failure:function(a){this.events.triggerEvent("loadend")},scope:this}),this.loaded=!0)},moveTo:function(a,b,c){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);this.visibility&&!this.loaded&&this.loadText()},parseData:function(a){a=a.responseText;var b={};OpenLayers.Util.extend(b,this.formatOptions);this.map&&!this.projection.equals(this.map.getProjectionObject())&&(b.externalProjection=this.projection,b.internalProjection=this.map.getProjectionObject());a=(new OpenLayers.Format.Text(b)).read(a);
2808 for(var b=0,c=a.length;b<c;b++){var d={},e=a[b],f,g,h;f=new OpenLayers.LonLat(e.geometry.x,e.geometry.y);e.style.graphicWidth&&e.style.graphicHeight&&(g=new OpenLayers.Size(e.style.graphicWidth,e.style.graphicHeight));void 0!==e.style.graphicXOffset&&void 0!==e.style.graphicYOffset&&(h=new OpenLayers.Pixel(e.style.graphicXOffset,e.style.graphicYOffset));null!=e.style.externalGraphic?d.icon=new OpenLayers.Icon(e.style.externalGraphic,g,h):(d.icon=OpenLayers.Marker.defaultIcon(),null!=g&&d.icon.setSize(g));
2809 null!=e.attributes.title&&null!=e.attributes.description&&(d.popupContentHTML="<h2>"+e.attributes.title+"</h2><p>"+e.attributes.description+"</p>");d.overflow=e.attributes.overflow||"auto";d=new OpenLayers.Feature(this,f,d);this.features.push(d);f=d.createMarker();null!=e.attributes.title&&null!=e.attributes.description&&f.events.register("click",d,this.markerClick);this.addMarker(f)}this.events.triggerEvent("loadend")},markerClick:function(a){var b=this==this.layer.selectedFeature;this.layer.selectedFeature=
2810 b?null:this;for(var c=0,d=this.layer.map.popups.length;c<d;c++)this.layer.map.removePopup(this.layer.map.popups[c]);b||this.layer.map.addPopup(this.createPopup());OpenLayers.Event.stop(a)},clearFeatures:function(){if(null!=this.features)for(;0<this.features.length;){var a=this.features[0];OpenLayers.Util.removeItem(this.features,a);a.destroy()}},CLASS_NAME:"OpenLayers.Layer.Text"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:"shiftKey",layerOptions:null,persist:!1,irregular:!1,citeCompliant:!1,angle:null,fixedRadius:!1,feature:null,layer:null,origin:null,initialize:function(a,b,c){c&&c.layerOptions&&c.layerOptions.styleMap||(this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style["default"],{}));OpenLayers.Handler.Drag.prototype.initialize.apply(this,[a,b,c]);this.options=c?c:{}},setOptions:function(a){OpenLayers.Util.extend(this.options,
2811 a);OpenLayers.Util.extend(this,a)},activate:function(){var a=!1;OpenLayers.Handler.Drag.prototype.activate.apply(this,arguments)&&(a=OpenLayers.Util.extend({displayInLayerSwitcher:!1,calculateInRange:OpenLayers.Function.True,wrapDateLine:this.citeCompliant},this.layerOptions),this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,a),this.map.addLayer(this.layer),a=!0);return a},deactivate:function(){var a=!1;OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)&&(this.dragging&&this.cancel(),
2812 null!=this.layer.map&&(this.layer.destroy(!1),this.feature&&this.feature.destroy()),this.feature=this.layer=null,a=!0);return a},down:function(a){this.fixedRadius=!!this.radius;a=this.layer.getLonLatFromViewPortPx(a.xy);this.origin=new OpenLayers.Geometry.Point(a.lon,a.lat);if(!this.fixedRadius||this.irregular)this.radius=this.map.getResolution();this.persist&&this.clear();this.feature=new OpenLayers.Feature.Vector;this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],
2813 {silent:!0});this.layer.drawFeature(this.feature,this.style)},move:function(a){var b=this.layer.getLonLatFromViewPortPx(a.xy),b=new OpenLayers.Geometry.Point(b.lon,b.lat);this.irregular?(a=Math.sqrt(2)*Math.abs(b.y-this.origin.y)/2,this.radius=Math.max(this.map.getResolution()/2,a)):this.fixedRadius?this.origin=b:(this.calculateAngle(b,a),this.radius=Math.max(this.map.getResolution()/2,b.distanceTo(this.origin)));this.modifyGeometry();if(this.irregular){a=b.x-this.origin.x;var b=b.y-this.origin.y,
2814 c;c=0==b?a/(this.radius*Math.sqrt(2)):a/b;this.feature.geometry.resize(1,this.origin,c);this.feature.geometry.move(a/2,b/2)}this.layer.drawFeature(this.feature,this.style)},up:function(a){this.finalize();this.start==this.last&&this.callback("done",[a.xy])},out:function(a){this.finalize()},createGeometry:function(){this.angle=Math.PI*(1/this.sides-0.5);this.snapAngle&&(this.angle+=this.snapAngle*(Math.PI/180));this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,
2815 this.sides,this.snapAngle)},modifyGeometry:function(){var a,b,c=this.feature.geometry.components[0];c.components.length!=this.sides+1&&(this.createGeometry(),c=this.feature.geometry.components[0]);for(var d=0;d<this.sides;++d)b=c.components[d],a=this.angle+2*d*Math.PI/this.sides,b.x=this.origin.x+this.radius*Math.cos(a),b.y=this.origin.y+this.radius*Math.sin(a),b.clearBounds()},calculateAngle:function(a,b){var c=Math.atan2(a.y-this.origin.y,a.x-this.origin.x);if(this.snapAngle&&this.snapToggle&&!b[this.snapToggle]){var d=
2816 Math.PI/180*this.snapAngle;this.angle=Math.round(c/d)*d}else this.angle=c},cancel:function(){this.callback("cancel",null);this.finalize()},finalize:function(){this.origin=null;this.radius=this.options.radius},clear:function(){this.layer&&(this.layer.renderer.clear(),this.layer.destroyFeatures())},callback:function(a,b){this.callbacks[a]&&this.callbacks[a].apply(this.control,[this.feature.geometry.clone()]);this.persist||"done"!=a&&"cancel"!=a||this.clear()},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Control.SLDSelect=OpenLayers.Class(OpenLayers.Control,{clearOnDeactivate:!1,layers:null,callbacks:null,selectionSymbolizer:{Polygon:{fillColor:"#FF0000",stroke:!1},Line:{strokeColor:"#FF0000",strokeWidth:2},Point:{graphicName:"square",fillColor:"#FF0000",pointRadius:5}},layerOptions:null,sketchStyle:null,wfsCache:{},layerCache:{},initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);this.callbacks=OpenLayers.Util.extend({done:this.select,click:this.select},this.callbacks);
2817 this.handlerOptions=this.handlerOptions||{};this.layerOptions=OpenLayers.Util.applyDefaults(this.layerOptions,{displayInLayerSwitcher:!1,tileOptions:{maxGetUrlLength:2048}});this.sketchStyle&&(this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":this.sketchStyle})}));this.handler=new a(this,this.callbacks,this.handlerOptions)},destroy:function(){for(var a in this.layerCache)delete this.layerCache[a];for(a in this.wfsCache)delete this.wfsCache[a];
2818 OpenLayers.Control.prototype.destroy.apply(this,arguments)},coupleLayerVisiblity:function(a){this.setVisibility(a.object.getVisibility())},createSelectionLayer:function(a){var b;if(this.layerCache[a.id])b=this.layerCache[a.id];else{b=new OpenLayers.Layer.WMS(a.name,a.url,a.params,OpenLayers.Util.applyDefaults(this.layerOptions,a.getOptions()));this.layerCache[a.id]=b;if(!1===this.layerOptions.displayInLayerSwitcher)a.events.on({visibilitychanged:this.coupleLayerVisiblity,scope:b});this.map.addLayer(b)}return b},
2819 createSLD:function(a,b,c){for(var d={version:"1.0.0",namedLayers:{}},e=(""+a.params.LAYERS).split(","),f=0,g=e.length;f<g;f++){var h=e[f];d.namedLayers[h]={name:h,userStyles:[]};var k=this.selectionSymbolizer,l=c[f];0<=l.type.indexOf("Polygon")?k={Polygon:this.selectionSymbolizer.Polygon}:0<=l.type.indexOf("LineString")?k={Line:this.selectionSymbolizer.Line}:0<=l.type.indexOf("Point")&&(k={Point:this.selectionSymbolizer.Point});d.namedLayers[h].userStyles.push({name:"default",rules:[new OpenLayers.Rule({symbolizer:k,
2820 filter:b[f],maxScaleDenominator:a.options.minScale})]})}return(new OpenLayers.Format.SLD({srsName:this.map.getProjection()})).write(d)},parseDescribeLayer:function(a){var b=new OpenLayers.Format.WMSDescribeLayer,c=a.responseXML;c&&c.documentElement||(c=a.responseText);a=b.read(c);for(var b=[],c=null,d=0,e=a.length;d<e;d++)"WFS"==a[d].owsType&&(b.push(a[d].typeName),c=a[d].owsURL);OpenLayers.Request.GET({url:c,params:{SERVICE:"WFS",TYPENAME:b.toString(),REQUEST:"DescribeFeatureType",VERSION:"1.0.0"},
2821 callback:function(a){var b=new OpenLayers.Format.WFSDescribeFeatureType,c=a.responseXML;c&&c.documentElement||(c=a.responseText);a=b.read(c);this.control.wfsCache[this.layer.id]=a;this.control._queue&&this.control.applySelection()},scope:this})},getGeometryAttributes:function(a){var b=[];a=this.wfsCache[a.id];for(var c=0,d=a.featureTypes.length;c<d;c++)for(var e=a.featureTypes[c].properties,f=0,g=e.length;f<g;f++){var h=e[f],k=h.type;(0<=k.indexOf("LineString")||0<=k.indexOf("GeometryAssociationType")||
2822 0<=k.indexOf("GeometryPropertyType")||0<=k.indexOf("Point")||0<=k.indexOf("Polygon"))&&b.push(h)}return b},activate:function(){var a=OpenLayers.Control.prototype.activate.call(this);if(a)for(var b=0,c=this.layers.length;b<c;b++){var d=this.layers[b];d&&!this.wfsCache[d.id]&&OpenLayers.Request.GET({url:d.url,params:{SERVICE:"WMS",VERSION:d.params.VERSION,LAYERS:d.params.LAYERS,REQUEST:"DescribeLayer"},callback:this.parseDescribeLayer,scope:{layer:d,control:this}})}return a},deactivate:function(){var a=
2823 OpenLayers.Control.prototype.deactivate.call(this);if(a)for(var b=0,c=this.layers.length;b<c;b++){var d=this.layers[b];if(d&&!0===this.clearOnDeactivate){var e=this.layerCache,f=e[d.id];f&&(d.events.un({visibilitychanged:this.coupleLayerVisiblity,scope:f}),f.destroy(),delete e[d.id])}}return a},setLayers:function(a){this.active?(this.deactivate(),this.layers=a,this.activate()):this.layers=a},createFilter:function(a,b){var c=null;this.handler instanceof OpenLayers.Handler.RegularPolygon?c=!0===this.handler.irregular?
2824 new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:a.name,value:b.getBounds()}):new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:a.name,value:b}):this.handler instanceof OpenLayers.Handler.Polygon?c=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:a.name,value:b}):this.handler instanceof OpenLayers.Handler.Path?c=0<=a.type.indexOf("Point")?new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,
2825 property:a.name,distance:0.01*this.map.getExtent().getWidth(),distanceUnits:this.map.getUnits(),value:b}):new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:a.name,value:b}):this.handler instanceof OpenLayers.Handler.Click&&(c=0<=a.type.indexOf("Polygon")?new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:a.name,value:b}):new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:a.name,distance:0.01*this.map.getExtent().getWidth(),
2826 distanceUnits:this.map.getUnits(),value:b}));return c},select:function(a){this._queue=function(){for(var b=0,c=this.layers.length;b<c;b++){for(var d=this.layers[b],e=this.getGeometryAttributes(d),f=[],g=0,h=e.length;g<h;g++){var k=e[g];if(null!==k){if(!(a instanceof OpenLayers.Geometry)){var l=this.map.getLonLatFromPixel(a.xy);a=new OpenLayers.Geometry.Point(l.lon,l.lat)}k=this.createFilter(k,a);null!==k&&f.push(k)}}g=this.createSelectionLayer(d);this.events.triggerEvent("selected",{layer:d,filters:f});
2827 d=this.createSLD(d,f,e);g.mergeNewParams({SLD_BODY:d});delete this._queue}};this.applySelection()},applySelection:function(){for(var a=!0,b=0,c=this.layers.length;b<c;b++)if(!this.wfsCache[this.layers[b].id]){a=!1;break}a&&this._queue.call(this)},CLASS_NAME:"OpenLayers.Control.SLDSelect"});OpenLayers.Control.Scale=OpenLayers.Class(OpenLayers.Control,{element:null,geodesic:!1,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);this.element=OpenLayers.Util.getElement(a)},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.element||(this.element=document.createElement("div"),this.div.appendChild(this.element));this.map.events.register("moveend",this,this.updateScale);this.updateScale();return this.div},updateScale:function(){var a;
2828 if(!0===this.geodesic){if(!this.map.getUnits())return;a=OpenLayers.INCHES_PER_UNIT;a=(this.map.getGeodesicPixelSize().w||1E-6)*a.km*OpenLayers.DOTS_PER_INCH}else a=this.map.getScale();a&&(a=9500<=a&&95E4>=a?Math.round(a/1E3)+"K":95E4<=a?Math.round(a/1E6)+"M":Math.round(a),this.element.innerHTML=OpenLayers.i18n("Scale = 1 : ${scaleDenom}",{scaleDenom:a}))},CLASS_NAME:"OpenLayers.Control.Scale"});OpenLayers.Layer.MapGuide=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,useHttpTile:!1,singleTile:!1,useOverlay:!1,useAsyncOverlay:!0,TILE_PARAMS:{operation:"GETTILEIMAGE",version:"1.2.0"},SINGLE_TILE_PARAMS:{operation:"GETMAPIMAGE",format:"PNG",locale:"en",clip:"1",version:"1.0.0"},OVERLAY_PARAMS:{operation:"GETDYNAMICMAPOVERLAYIMAGE",format:"PNG",locale:"en",clip:"1",version:"2.0.0"},FOLDER_PARAMS:{tileColumnsPerFolder:30,tileRowsPerFolder:30,format:"png",querystring:null},defaultSize:new OpenLayers.Size(300,
2829 300),tileOriginCorner:"tl",initialize:function(a,b,c,d){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);if(null==d||null==d.isBaseLayer)this.isBaseLayer="true"!=this.transparent&&!0!=this.transparent;d&&null!=d.useOverlay&&(this.useOverlay=d.useOverlay);this.singleTile?this.useOverlay?(OpenLayers.Util.applyDefaults(this.params,this.OVERLAY_PARAMS),this.useAsyncOverlay||(this.params.version="1.0.0")):OpenLayers.Util.applyDefaults(this.params,this.SINGLE_TILE_PARAMS):(this.useHttpTile?
2830 OpenLayers.Util.applyDefaults(this.params,this.FOLDER_PARAMS):OpenLayers.Util.applyDefaults(this.params,this.TILE_PARAMS),this.setTileSize(this.defaultSize))},clone:function(a){null==a&&(a=new OpenLayers.Layer.MapGuide(this.name,this.url,this.params,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){var b;b=a.getCenterLonLat();var c=this.map.getSize();this.singleTile?(a={setdisplaydpi:OpenLayers.DOTS_PER_INCH,setdisplayheight:c.h*this.ratio,setdisplaywidth:c.w*
2831 this.ratio,setviewcenterx:b.lon,setviewcentery:b.lat,setviewscale:this.map.getScale()},this.useOverlay&&!this.useAsyncOverlay&&(b={},b=OpenLayers.Util.extend(b,a),b.operation="GETVISIBLEMAPEXTENT",b.version="1.0.0",b.session=this.params.session,b.mapName=this.params.mapName,b.format="text/xml",b=this.getFullRequestString(b),OpenLayers.Request.GET({url:b,async:!1})),b=this.getFullRequestString(a)):(c=this.map.getResolution(),b=Math.floor((a.left-this.maxExtent.left)/c),b=Math.round(b/this.tileSize.w),
2832 a=Math.floor((this.maxExtent.top-a.top)/c),a=Math.round(a/this.tileSize.h),b=this.useHttpTile?this.getImageFilePath({tilecol:b,tilerow:a,scaleindex:this.resolutions.length-this.map.zoom-1}):this.getFullRequestString({tilecol:b,tilerow:a,scaleindex:this.resolutions.length-this.map.zoom-1}));return b},getFullRequestString:function(a,b){var c=null==b?this.url:b;"object"==typeof c&&(c=c[Math.floor(Math.random()*c.length)]);var d=c,e=OpenLayers.Util.extend({},this.params),e=OpenLayers.Util.extend(e,a),
2833 f=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(c)),g;for(g in e)g.toUpperCase()in f&&delete e[g];e=OpenLayers.Util.getParameterString(e);e=e.replace(/,/g,"+");""!=e&&(f=c.charAt(c.length-1),d="&"==f||"?"==f?d+e:-1==c.indexOf("?")?d+("?"+e):d+("&"+e));return d},getImageFilePath:function(a,b){var c=null==b?this.url:b;"object"==typeof c&&(c=c[Math.floor(Math.random()*c.length)]);var d="",e="";0>a.tilerow&&(d="-");d=0==a.tilerow?d+"0":d+Math.floor(Math.abs(a.tilerow/this.params.tileRowsPerFolder))*
2834 this.params.tileRowsPerFolder;0>a.tilecol&&(e="-");e=0==a.tilecol?e+"0":e+Math.floor(Math.abs(a.tilecol/this.params.tileColumnsPerFolder))*this.params.tileColumnsPerFolder;d="/S"+Math.floor(a.scaleindex)+"/"+this.params.basemaplayergroupname+"/R"+d+"/C"+e+"/"+a.tilerow%this.params.tileRowsPerFolder+"_"+a.tilecol%this.params.tileColumnsPerFolder+"."+this.params.format;this.params.querystring&&(d+="?"+this.params.querystring);return c+d},CLASS_NAME:"OpenLayers.Layer.MapGuide"});OpenLayers.Control.Measure=OpenLayers.Class(OpenLayers.Control,{callbacks:null,displaySystem:"metric",geodesic:!1,displaySystemUnits:{geographic:["dd"],english:["mi","ft","in"],metric:["km","m"]},partialDelay:300,delayedTrigger:null,persist:!1,immediate:!1,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);var c={done:this.measureComplete,point:this.measurePartial};this.immediate&&(c.modify=this.measureImmediate);this.callbacks=OpenLayers.Util.extend(c,this.callbacks);
2835 this.handlerOptions=OpenLayers.Util.extend({persist:this.persist},this.handlerOptions);this.handler=new a(this,this.callbacks,this.handlerOptions)},deactivate:function(){this.cancelDelay();return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},cancel:function(){this.cancelDelay();this.handler.cancel()},setImmediate:function(a){(this.immediate=a)?this.callbacks.modify=this.measureImmediate:delete this.callbacks.modify},updateHandler:function(a,b){var c=this.active;c&&this.deactivate();
2836 this.handler=new a(this,this.callbacks,b);c&&this.activate()},measureComplete:function(a){this.cancelDelay();this.measure(a,"measure")},measurePartial:function(a,b){this.cancelDelay();b=b.clone();this.handler.freehandMode(this.handler.evt)?this.measure(b,"measurepartial"):this.delayedTrigger=window.setTimeout(OpenLayers.Function.bind(function(){this.delayedTrigger=null;this.measure(b,"measurepartial")},this),this.partialDelay)},measureImmediate:function(a,b,c){c&&!this.handler.freehandMode(this.handler.evt)&&
2837 (this.cancelDelay(),this.measure(b.geometry,"measurepartial"))},cancelDelay:function(){null!==this.delayedTrigger&&(window.clearTimeout(this.delayedTrigger),this.delayedTrigger=null)},measure:function(a,b){var c,d;-1<a.CLASS_NAME.indexOf("LineString")?(c=this.getBestLength(a),d=1):(c=this.getBestArea(a),d=2);this.events.triggerEvent(b,{measure:c[0],units:c[1],order:d,geometry:a})},getBestArea:function(a){for(var b=this.displaySystemUnits[this.displaySystem],c,d,e=0,f=b.length;e<f&&!(c=b[e],d=this.getArea(a,
2838 c),1<d);++e);return[d,c]},getArea:function(a,b){var c,d;this.geodesic?(c=a.getGeodesicArea(this.map.getProjectionObject()),d="m"):(c=a.getArea(),d=this.map.getUnits());var e=OpenLayers.INCHES_PER_UNIT[b];e&&(c*=Math.pow(OpenLayers.INCHES_PER_UNIT[d]/e,2));return c},getBestLength:function(a){for(var b=this.displaySystemUnits[this.displaySystem],c,d,e=0,f=b.length;e<f&&!(c=b[e],d=this.getLength(a,c),1<d);++e);return[d,c]},getLength:function(a,b){var c,d;this.geodesic?(c=a.getGeodesicLength(this.map.getProjectionObject()),
2839 d="m"):(c=a.getLength(),d=this.map.getUnits());var e=OpenLayers.INCHES_PER_UNIT[b];e&&(c*=OpenLayers.INCHES_PER_UNIT[d]/e);return c},CLASS_NAME:"OpenLayers.Control.Measure"});OpenLayers.Format.WMC.v1_0_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd",initialize:function(a){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[a])},read_wmc_SRS:function(a,b){var c=this.getChildValue(b);"object"!=typeof a.projections&&(a.projections={});for(var c=c.split(/ +/),d=0,e=c.length;d<e;d++)a.projections[c[d]]=!0},write_wmc_Layer:function(a){var b=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,
2840 [a]);if(a.srs){var c=[],d;for(d in a.srs)c.push(d);b.appendChild(this.createElementDefaultNS("SRS",c.join(" ")))}b.appendChild(this.write_wmc_FormatList(a));b.appendChild(this.write_wmc_StyleList(a));a.dimensions&&b.appendChild(this.write_wmc_DimensionList(a));b.appendChild(this.write_wmc_LayerExtension(a))},CLASS_NAME:"OpenLayers.Format.WMC.v1_0_0"});OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:!0,anchor:null,initialize:function(a,b,c,d,e,f,g){OpenLayers.Popup.prototype.initialize.apply(this,[a,b,c,d,f,g]);this.anchor=null!=e?e:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)}},destroy:function(){this.relativePosition=this.anchor=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments)},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments)},
2841 moveTo:function(a){var b=this.relativePosition;this.relativePosition=this.calculateRelativePosition(a);OpenLayers.Popup.prototype.moveTo.call(this,this.calculateNewPx(a));this.relativePosition!=b&&this.updateRelativePosition()},setSize:function(a){OpenLayers.Popup.prototype.setSize.apply(this,arguments);if(this.lonlat&&this.map){var b=this.map.getLayerPxFromLonLat(this.lonlat);this.moveTo(b)}},calculateRelativePosition:function(a){a=this.map.getLonLatFromLayerPx(a);a=this.map.getExtent().determineQuadrant(a);
2842 return OpenLayers.Bounds.oppositeQuadrant(a)},updateRelativePosition:function(){},calculateNewPx:function(a){a=a.offset(this.anchor.offset);var b=this.size||this.contentSize,c="t"==this.relativePosition.charAt(0);a.y+=c?-b.h:this.anchor.size.h;c="l"==this.relativePosition.charAt(1);a.x+=c?-b.w:this.anchor.size.w;return a},CLASS_NAME:"OpenLayers.Popup.Anchored"});OpenLayers.Popup.Framed=OpenLayers.Class(OpenLayers.Popup.Anchored,{imageSrc:null,imageSize:null,isAlphaImage:!1,positionBlocks:null,blocks:null,fixedRelativePosition:!1,initialize:function(a,b,c,d,e,f,g){OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);this.fixedRelativePosition&&(this.updateRelativePosition(),this.calculateRelativePosition=function(a){return this.relativePosition});this.contentDiv.style.position="absolute";this.contentDiv.style.zIndex=1;f&&(this.closeDiv.style.zIndex=
2843 1);this.groupDiv.style.position="absolute";this.groupDiv.style.top="0px";this.groupDiv.style.left="0px";this.groupDiv.style.height="100%";this.groupDiv.style.width="100%"},destroy:function(){this.isAlphaImage=this.imageSize=this.imageSrc=null;this.fixedRelativePosition=!1;this.positionBlocks=null;for(var a=0;a<this.blocks.length;a++){var b=this.blocks[a];b.image&&b.div.removeChild(b.image);b.image=null;b.div&&this.groupDiv.removeChild(b.div);b.div=null}this.blocks=null;OpenLayers.Popup.Anchored.prototype.destroy.apply(this,
2844 arguments)},setBackgroundColor:function(a){},setBorder:function(){},setOpacity:function(a){},setSize:function(a){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.updateBlocks()},updateRelativePosition:function(){this.padding=this.positionBlocks[this.relativePosition].padding;if(this.closeDiv){var a=this.getContentDivPadding();this.closeDiv.style.right=a.right+this.padding.right+"px";this.closeDiv.style.top=a.top+this.padding.top+"px"}this.updateBlocks()},calculateNewPx:function(a){var b=
2845 OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(this,arguments);return b=b.offset(this.positionBlocks[this.relativePosition].offset)},createBlocks:function(){this.blocks=[];var a=null,b;for(b in this.positionBlocks){a=b;break}a=this.positionBlocks[a];for(b=0;b<a.blocks.length;b++){var c={};this.blocks.push(c);c.div=OpenLayers.Util.createDiv(this.id+"_FrameDecorationDiv_"+b,null,null,null,"absolute",null,"hidden",null);c.image=(this.isAlphaImage?OpenLayers.Util.createAlphaImageDiv:OpenLayers.Util.createImage)(this.id+
2846 "_FrameDecorationImg_"+b,null,this.imageSize,this.imageSrc,"absolute",null,null,null);c.div.appendChild(c.image);this.groupDiv.appendChild(c.div)}},updateBlocks:function(){this.blocks||this.createBlocks();if(this.size&&this.relativePosition){for(var a=this.positionBlocks[this.relativePosition],b=0;b<a.blocks.length;b++){var c=a.blocks[b],d=this.blocks[b],e=c.anchor.left,f=c.anchor.bottom,g=c.anchor.right,h=c.anchor.top,k=isNaN(c.size.w)?this.size.w-(g+e):c.size.w,l=isNaN(c.size.h)?this.size.h-(f+
2847 h):c.size.h;d.div.style.width=(0>k?0:k)+"px";d.div.style.height=(0>l?0:l)+"px";d.div.style.left=null!=e?e+"px":"";d.div.style.bottom=null!=f?f+"px":"";d.div.style.right=null!=g?g+"px":"";d.div.style.top=null!=h?h+"px":"";d.image.style.left=c.position.x+"px";d.image.style.top=c.position.y+"px"}this.contentDiv.style.left=this.padding.left+"px";this.contentDiv.style.top=this.padding.top+"px"}},CLASS_NAME:"OpenLayers.Popup.Framed"});OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:!0,panMapIfOutOfView:!0,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:!1,fixedRelativePosition:!1,positionBlocks:{tl:{offset:new OpenLayers.Pixel(44,0),padding:new OpenLayers.Bounds(8,40,8,9),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,
2848 50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,18),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-632)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(0,-688)}]},tr:{offset:new OpenLayers.Pixel(-45,0),padding:new OpenLayers.Bounds(8,40,8,9),blocks:[{size:new OpenLayers.Size("auto",
2849 "auto"),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,19),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-631)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(0,
2850 0,null,null),position:new OpenLayers.Pixel(-215,-687)}]},bl:{offset:new OpenLayers.Pixel(45,0),padding:new OpenLayers.Bounds(8,9,8,40),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,
2851 21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(null,null,0,0),position:new OpenLayers.Pixel(-101,-674)}]},br:{offset:new OpenLayers.Pixel(-44,0),padding:new OpenLayers.Bounds(8,9,8,40),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,
2852 0)},{size:new OpenLayers.Size("auto",21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(0,null,null,0),position:new OpenLayers.Pixel(-311,-674)}]}},minSize:new OpenLayers.Size(105,10),maxSize:new OpenLayers.Size(1200,660),initialize:function(a,b,c,d,e,f,g){this.imageSrc=OpenLayers.Util.getImageLocation("cloud-popup-relative.png");
2853 OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Tile.Image.IFrame={useIFrame:null,blankImageUrl:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",draw:function(){if(OpenLayers.Tile.Image.prototype.shouldDraw.call(this)){var a=this.layer.getURL(this.bounds),b=this.useIFrame;this.useIFrame=null!==this.maxGetUrlLength&&!this.layer.async&&a.length>this.maxGetUrlLength;a=b&&!this.useIFrame;b=!b&&this.useIFrame;if(a||b)this.imgDiv&&this.imgDiv.parentNode===this.frame&&this.frame.removeChild(this.imgDiv),this.imgDiv=
2854 null,a&&this.frame.removeChild(this.frame.firstChild)}return OpenLayers.Tile.Image.prototype.draw.apply(this,arguments)},getImage:function(){if(!0===this.useIFrame){if(!this.frame.childNodes.length){var a=document.createElement("div"),b=a.style;b.position="absolute";b.width="100%";b.height="100%";b.zIndex=1;b.backgroundImage="url("+this.blankImageUrl+")";this.frame.appendChild(a)}a=this.id+"_iFrame";9>parseFloat(navigator.appVersion.split("MSIE")[1])?(b=document.createElement('<iframe name="'+a+'">'),
2855 b.style.backgroundColor="#FFFFFF",b.style.filter="chroma(color=#FFFFFF)"):(b=document.createElement("iframe"),b.style.backgroundColor="transparent",b.name=a);b.scrolling="no";b.marginWidth="0px";b.marginHeight="0px";b.frameBorder="0";b.style.position="absolute";b.style.width="100%";b.style.height="100%";1>this.layer.opacity&&OpenLayers.Util.modifyDOMElement(b,null,null,null,null,null,null,this.layer.opacity);this.frame.appendChild(b);return this.imgDiv=b}return OpenLayers.Tile.Image.prototype.getImage.apply(this,
2856 arguments)},createRequestForm:function(){var a=document.createElement("form");a.method="POST";var b=this.layer.params._OLSALT,b=(b?b+"_":"")+this.bounds.toBBOX();a.action=OpenLayers.Util.urlAppend(this.layer.url,b);a.target=this.id+"_iFrame";this.layer.getImageSize();var b=OpenLayers.Util.getParameters(this.url),c,d;for(d in b)c=document.createElement("input"),c.type="hidden",c.name=d,c.value=b[d],a.appendChild(c);return a},setImgSrc:function(a){if(!0===this.useIFrame)if(a){var b=this.createRequestForm();
2857 this.frame.appendChild(b);b.submit();this.frame.removeChild(b)}else this.imgDiv.parentNode===this.frame&&(this.frame.removeChild(this.imgDiv),this.imgDiv=null);else OpenLayers.Tile.Image.prototype.setImgSrc.apply(this,arguments)},onImageLoad:function(){OpenLayers.Tile.Image.prototype.onImageLoad.apply(this,arguments);!0===this.useIFrame&&(this.imgDiv.style.opacity=1,this.frame.style.opacity=this.layer.opacity)},createBackBuffer:function(){var a;!1===this.useIFrame&&(a=OpenLayers.Tile.Image.prototype.createBackBuffer.call(this));
2858 return a}};OpenLayers.Format.SOSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.SOSCapabilities"});OpenLayers.Format.SOSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.SOSCapabilities,{namespaces:{ows:"http://www.opengis.net/ows/1.1",sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a]);this.options=a},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,
2859 [a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},readers:{gml:OpenLayers.Util.applyDefaults({name:function(a,b){b.name=this.getChildValue(a)},TimePeriod:function(a,b){b.timePeriod={};this.readChildNodes(a,b.timePeriod)},beginPosition:function(a,b){b.beginPosition=this.getChildValue(a)},endPosition:function(a,b){b.endPosition=this.getChildValue(a)}},OpenLayers.Format.GML.v3.prototype.readers.gml),sos:{Capabilities:function(a,b){this.readChildNodes(a,b)},Contents:function(a,
2860 b){b.contents={};this.readChildNodes(a,b.contents)},ObservationOfferingList:function(a,b){b.offeringList={};this.readChildNodes(a,b.offeringList)},ObservationOffering:function(a,b){var c=this.getAttributeNS(a,this.namespaces.gml,"id");b[c]={procedures:[],observedProperties:[],featureOfInterestIds:[],responseFormats:[],resultModels:[],responseModes:[]};this.readChildNodes(a,b[c])},time:function(a,b){b.time={};this.readChildNodes(a,b.time)},procedure:function(a,b){b.procedures.push(this.getAttributeNS(a,
2861 this.namespaces.xlink,"href"))},observedProperty:function(a,b){b.observedProperties.push(this.getAttributeNS(a,this.namespaces.xlink,"href"))},featureOfInterest:function(a,b){b.featureOfInterestIds.push(this.getAttributeNS(a,this.namespaces.xlink,"href"))},responseFormat:function(a,b){b.responseFormats.push(this.getChildValue(a))},resultModel:function(a,b){b.resultModels.push(this.getChildValue(a))},responseMode:function(a,b){b.responseModes.push(this.getChildValue(a))}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},
2862 CLASS_NAME:"OpenLayers.Format.SOSCapabilities.v1_0_0"});OpenLayers.Handler.Pinch=OpenLayers.Class(OpenLayers.Handler,{started:!1,stopDown:!1,pinching:!1,last:null,start:null,touchstart:function(a){var b=!0;this.pinching=!1;if(OpenLayers.Event.isMultiTouch(a))this.started=!0,this.last=this.start={distance:this.getDistance(a.touches),delta:0,scale:1},this.callback("start",[a,this.start]),b=!this.stopDown;else{if(this.started)return!1;this.started=!1;this.last=this.start=null}OpenLayers.Event.preventDefault(a);return b},touchmove:function(a){if(this.started&&
2863 OpenLayers.Event.isMultiTouch(a)){this.pinching=!0;var b=this.getPinchData(a);this.callback("move",[a,b]);this.last=b;OpenLayers.Event.stop(a)}else if(this.started)return!1;return!0},touchend:function(a){return this.started&&!OpenLayers.Event.isMultiTouch(a)?(this.pinching=this.started=!1,this.callback("done",[a,this.start,this.last]),this.last=this.start=null,!1):!0},activate:function(){var a=!1;OpenLayers.Handler.prototype.activate.apply(this,arguments)&&(this.pinching=!1,a=!0);return a},deactivate:function(){var a=
2864 !1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.pinching=this.started=!1,this.last=this.start=null,a=!0);return a},getDistance:function(a){var b=a[0];a=a[1];return Math.sqrt(Math.pow(b.olClientX-a.olClientX,2)+Math.pow(b.olClientY-a.olClientY,2))},getPinchData:function(a){a=this.getDistance(a.touches);return{distance:a,delta:this.last.distance-a,scale:a/this.start.distance}},CLASS_NAME:"OpenLayers.Handler.Pinch"});OpenLayers.Control.NavToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(a){OpenLayers.Control.Panel.prototype.initialize.apply(this,[a]);this.addControls([new OpenLayers.Control.Navigation,new OpenLayers.Control.ZoomBox])},draw:function(){var a=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);null===this.defaultControl&&(this.defaultControl=this.controls[0]);return a},CLASS_NAME:"OpenLayers.Control.NavToolbar"});OpenLayers.Strategy.Refresh=OpenLayers.Class(OpenLayers.Strategy,{force:!1,interval:0,timer:null,activate:function(){var a=OpenLayers.Strategy.prototype.activate.call(this);a&&(!0===this.layer.visibility&&this.start(),this.layer.events.on({visibilitychanged:this.reset,scope:this}));return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&(this.stop(),this.layer.events.un({visibilitychanged:this.reset,scope:this}));return a},reset:function(){!0===this.layer.visibility?
2865 this.start():this.stop()},start:function(){this.interval&&("number"===typeof this.interval&&0<this.interval)&&(this.timer=window.setInterval(OpenLayers.Function.bind(this.refresh,this),this.interval))},refresh:function(){this.layer&&(this.layer.refresh&&"function"==typeof this.layer.refresh)&&this.layer.refresh({force:this.force})},stop:function(){null!==this.timer&&(window.clearInterval(this.timer),this.timer=null)},CLASS_NAME:"OpenLayers.Strategy.Refresh"});OpenLayers.Layer.ArcGIS93Rest=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{format:"png"},isBaseLayer:!0,initialize:function(a,b,c,d){var e=[];c=OpenLayers.Util.upperCaseObject(c);e.push(a,b,c,d);OpenLayers.Layer.Grid.prototype.initialize.apply(this,e);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));this.params.TRANSPARENT&&"true"==this.params.TRANSPARENT.toString().toLowerCase()&&(null!=d&&d.isBaseLayer||(this.isBaseLayer=!1),"jpg"==this.params.FORMAT&&
2866 (this.params.FORMAT=OpenLayers.Util.alphaHack()?"gif":"png"))},clone:function(a){null==a&&(a=new OpenLayers.Layer.ArcGIS93Rest(this.name,this.url,this.params,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){a=this.adjustBounds(a);var b=this.projection.getCode().split(":"),b=b[b.length-1],c=this.getImageSize();a={BBOX:a.toBBOX(),SIZE:c.w+","+c.h,F:"image",BBOXSR:b,IMAGESR:b};if(this.layerDefs){var b=[],d;for(d in this.layerDefs)this.layerDefs.hasOwnProperty(d)&&
2867 this.layerDefs[d]&&(b.push(d),b.push(":"),b.push(this.layerDefs[d]),b.push(";"));0<b.length&&(a.LAYERDEFS=b.join(""))}return this.getFullRequestString(a)},setLayerFilter:function(a,b){this.layerDefs||(this.layerDefs={});b?this.layerDefs[a]=b:delete this.layerDefs[a]},clearLayerFilter:function(a){a?delete this.layerDefs[a]:delete this.layerDefs},mergeNewParams:function(a){a=[OpenLayers.Util.upperCaseObject(a)];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,a)},CLASS_NAME:"OpenLayers.Layer.ArcGIS93Rest"});OpenLayers.Handler.Hover=OpenLayers.Class(OpenLayers.Handler,{delay:500,pixelTolerance:null,stopMove:!1,px:null,timerId:null,mousemove:function(a){this.passesTolerance(a.xy)&&(this.clearTimer(),this.callback("move",[a]),this.px=a.xy,a=OpenLayers.Util.extend({},a),this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,a),this.delay));return!this.stopMove},mouseout:function(a){OpenLayers.Util.mouseLeft(a,this.map.viewPortDiv)&&(this.clearTimer(),this.callback("move",[a]));return!0},
2868 passesTolerance:function(a){var b=!0;this.pixelTolerance&&this.px&&Math.sqrt(Math.pow(this.px.x-a.x,2)+Math.pow(this.px.y-a.y,2))<this.pixelTolerance&&(b=!1);return b},clearTimer:function(){null!=this.timerId&&(window.clearTimeout(this.timerId),this.timerId=null)},delayedCall:function(a){this.callback("pause",[a])},deactivate:function(){var a=!1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.clearTimer(),a=!0);return a},CLASS_NAME:"OpenLayers.Handler.Hover"});OpenLayers.Control.GetFeature=OpenLayers.Class(OpenLayers.Control,{protocol:null,multipleKey:null,toggleKey:null,modifiers:null,multiple:!1,click:!0,single:!0,clickout:!0,toggle:!1,clickTolerance:5,hover:!1,box:!1,maxFeatures:10,features:null,hoverFeature:null,handlers:null,hoverResponse:null,filterType:OpenLayers.Filter.Spatial.BBOX,initialize:function(a){a.handlerOptions=a.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[a]);this.features={};this.handlers={};this.click&&(this.handlers.click=
2869 new OpenLayers.Handler.Click(this,{click:this.selectClick},this.handlerOptions.click||{}));this.box&&(this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},OpenLayers.Util.extend(this.handlerOptions.box,{boxDivClassName:"olHandlerBoxSelectFeature"})));this.hover&&(this.handlers.hover=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.selectHover},OpenLayers.Util.extend(this.handlerOptions.hover,{delay:250,pixelTolerance:2})))},activate:function(){if(!this.active)for(var a in this.handlers)this.handlers[a].activate();
2870 return OpenLayers.Control.prototype.activate.apply(this,arguments)},deactivate:function(){if(this.active)for(var a in this.handlers)this.handlers[a].deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},selectClick:function(a){var b=this.pixelToBounds(a.xy);this.setModifiers(a);this.request(b,{single:this.single})},selectBox:function(a){var b;if(a instanceof OpenLayers.Bounds)b=this.map.getLonLatFromPixel({x:a.left,y:a.bottom}),a=this.map.getLonLatFromPixel({x:a.right,
2871 y:a.top}),b=new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat);else{if(this.click)return;b=this.pixelToBounds(a)}this.setModifiers(this.handlers.box.dragHandler.evt);this.request(b)},selectHover:function(a){a=this.pixelToBounds(a.xy);this.request(a,{single:!0,hover:!0})},cancelHover:function(){this.hoverResponse&&(this.protocol.abort(this.hoverResponse),this.hoverResponse=null,OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait"))},request:function(a,b){b=b||{};var c=new OpenLayers.Filter.Spatial({type:this.filterType,
2872 value:a});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");c=this.protocol.read({maxFeatures:!0==b.single?this.maxFeatures:void 0,filter:c,callback:function(c){c.success()&&(c.features.length?!0==b.single?this.selectBestFeature(c.features,a.getCenterLonLat(),b):this.select(c.features):b.hover?this.hoverSelect():(this.events.triggerEvent("clickout"),this.clickout&&this.unselectAll()));OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait")},scope:this});!0==b.hover&&(this.hoverResponse=
2873 c)},selectBestFeature:function(a,b,c){c=c||{};if(a.length){b=new OpenLayers.Geometry.Point(b.lon,b.lat);for(var d,e,f,g=Number.MAX_VALUE,h=0;h<a.length&&!(d=a[h],d.geometry&&(f=b.distanceTo(d.geometry,{edge:!1}),f<g&&(g=f,e=d,0==g)));++h);!0==c.hover?this.hoverSelect(e):this.select(e||a)}},setModifiers:function(a){this.modifiers={multiple:this.multiple||this.multipleKey&&a[this.multipleKey],toggle:this.toggle||this.toggleKey&&a[this.toggleKey]}},select:function(a){this.modifiers.multiple||this.modifiers.toggle||
2874 this.unselectAll();OpenLayers.Util.isArray(a)||(a=[a]);var b=this.events.triggerEvent("beforefeaturesselected",{features:a});if(!1!==b){for(var c=[],d,e=0,f=a.length;e<f;++e)d=a[e],this.features[d.fid||d.id]?this.modifiers.toggle&&this.unselect(this.features[d.fid||d.id]):(b=this.events.triggerEvent("beforefeatureselected",{feature:d}),!1!==b&&(this.features[d.fid||d.id]=d,c.push(d),this.events.triggerEvent("featureselected",{feature:d})));this.events.triggerEvent("featuresselected",{features:c})}},
2875 hoverSelect:function(a){var b=a?a.fid||a.id:null,c=this.hoverFeature?this.hoverFeature.fid||this.hoverFeature.id:null;c&&c!=b&&(this.events.triggerEvent("outfeature",{feature:this.hoverFeature}),this.hoverFeature=null);b&&b!=c&&(this.events.triggerEvent("hoverfeature",{feature:a}),this.hoverFeature=a)},unselect:function(a){delete this.features[a.fid||a.id];this.events.triggerEvent("featureunselected",{feature:a})},unselectAll:function(){for(var a in this.features)this.unselect(this.features[a])},
2876 setMap:function(a){for(var b in this.handlers)this.handlers[b].setMap(a);OpenLayers.Control.prototype.setMap.apply(this,arguments)},pixelToBounds:function(a){var b=a.add(-this.clickTolerance/2,this.clickTolerance/2);a=a.add(this.clickTolerance/2,-this.clickTolerance/2);b=this.map.getLonLatFromPixel(b);a=this.map.getLonLatFromPixel(a);return new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat)},CLASS_NAME:"OpenLayers.Control.GetFeature"});OpenLayers.Format.QueryStringFilter=function(){function a(a){a=a.replace(/%/g,"\\%");a=a.replace(/\\\\\.(\*)?/g,function(a,b){return b?a:"\\\\_"});a=a.replace(/\\\\\.\*/g,"\\\\%");a=a.replace(/(\\)?\.(\*)?/g,function(a,b,c){return b||c?a:"_"});a=a.replace(/(\\)?\.\*/g,function(a,b){return b?a:"%"});a=a.replace(/\\\./g,".");return a=a.replace(/(\\)?\\\*/g,function(a,b){return b?a:"*"})}var b={};b[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";b[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";b[OpenLayers.Filter.Comparison.LESS_THAN]=
2877 "lt";b[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";b[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";b[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";b[OpenLayers.Filter.Comparison.LIKE]="ilike";return OpenLayers.Class(OpenLayers.Format,{wildcarded:!1,srsInBBOX:!1,write:function(c,d){d=d||{};var e=c.CLASS_NAME,e=e.substring(e.lastIndexOf(".")+1);switch(e){case "Spatial":switch(c.type){case OpenLayers.Filter.Spatial.BBOX:d.bbox=c.value.toArray();this.srsInBBOX&&c.projection&&
2878 d.bbox.push(c.projection.getCode());break;case OpenLayers.Filter.Spatial.DWITHIN:d.tolerance=c.distance;case OpenLayers.Filter.Spatial.WITHIN:d.lon=c.value.x;d.lat=c.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+c.type)}break;case "Comparison":e=b[c.type];if(void 0!==e){var f=c.value;c.type==OpenLayers.Filter.Comparison.LIKE&&(f=a(f),this.wildcarded&&(f="%"+f+"%"));d[c.property+"__"+e]=f;d.queryable=d.queryable||[];d.queryable.push(c.property)}else OpenLayers.Console.warn("Unknown comparison filter type "+
2879 c.type);break;case "Logical":if(c.type===OpenLayers.Filter.Logical.AND)for(e=0,f=c.filters.length;e<f;e++)d=this.write(c.filters[e],d);else OpenLayers.Console.warn("Unsupported logical filter type "+c.type);break;default:OpenLayers.Console.warn("Unknown filter type "+e)}return d},CLASS_NAME:"OpenLayers.Format.QueryStringFilter"})}();OpenLayers.Control.MousePosition=OpenLayers.Class(OpenLayers.Control,{autoActivate:!0,element:null,prefix:"",separator:", ",suffix:"",numDigits:5,granularity:10,emptyString:null,lastXy:null,displayProjection:null,destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments)},activate:function(){return OpenLayers.Control.prototype.activate.apply(this,arguments)?(this.map.events.register("mousemove",this,this.redraw),this.map.events.register("mouseout",this,this.reset),
2880 this.redraw(),!0):!1},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments)?(this.map.events.unregister("mousemove",this,this.redraw),this.map.events.unregister("mouseout",this,this.reset),this.element.innerHTML="",!0):!1},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.element||(this.div.left="",this.div.top="",this.element=this.div);return this.div},redraw:function(a){var b;if(null==a)this.reset();else if(null==this.lastXy||Math.abs(a.xy.x-
2881 this.lastXy.x)>this.granularity||Math.abs(a.xy.y-this.lastXy.y)>this.granularity)this.lastXy=a.xy;else if(b=this.map.getLonLatFromPixel(a.xy))this.displayProjection&&b.transform(this.map.getProjectionObject(),this.displayProjection),this.lastXy=a.xy,a=this.formatOutput(b),a!=this.element.innerHTML&&(this.element.innerHTML=a)},reset:function(a){null!=this.emptyString&&(this.element.innerHTML=this.emptyString)},formatOutput:function(a){var b=parseInt(this.numDigits);return this.prefix+a.lon.toFixed(b)+
2882 this.separator+a.lat.toFixed(b)+this.suffix},CLASS_NAME:"OpenLayers.Control.MousePosition"});OpenLayers.Control.Geolocate=OpenLayers.Class(OpenLayers.Control,{geolocation:null,available:"geolocation"in navigator,bind:!0,watch:!1,geolocationOptions:null,destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments)},activate:function(){this.available&&!this.geolocation&&(this.geolocation=navigator.geolocation);return this.geolocation?OpenLayers.Control.prototype.activate.apply(this,arguments)?(this.watch?this.watchId=this.geolocation.watchPosition(OpenLayers.Function.bind(this.geolocate,
2883 this),OpenLayers.Function.bind(this.failure,this),this.geolocationOptions):this.getCurrentLocation(),!0):!1:(this.events.triggerEvent("locationuncapable"),!1)},deactivate:function(){this.active&&null!==this.watchId&&this.geolocation.clearWatch(this.watchId);return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},geolocate:function(a){var b=(new OpenLayers.LonLat(a.coords.longitude,a.coords.latitude)).transform(new OpenLayers.Projection("EPSG:4326"),this.map.getProjectionObject());this.bind&&
2884 this.map.setCenter(b);this.events.triggerEvent("locationupdated",{position:a,point:new OpenLayers.Geometry.Point(b.lon,b.lat)})},getCurrentLocation:function(){if(!this.active||this.watch)return!1;this.geolocation.getCurrentPosition(OpenLayers.Function.bind(this.geolocate,this),OpenLayers.Function.bind(this.failure,this),this.geolocationOptions);return!0},failure:function(a){this.events.triggerEvent("locationfailed",{error:a})},CLASS_NAME:"OpenLayers.Control.Geolocate"});OpenLayers.Tile.UTFGrid=OpenLayers.Class(OpenLayers.Tile,{url:null,utfgridResolution:2,json:null,format:null,destroy:function(){this.clear();OpenLayers.Tile.prototype.destroy.apply(this,arguments)},draw:function(){var a=OpenLayers.Tile.prototype.draw.apply(this,arguments);if(a)if(this.isLoading?(this.abortLoading(),this.events.triggerEvent("reload")):(this.isLoading=!0,this.events.triggerEvent("loadstart")),this.url=this.layer.getURL(this.bounds),this.layer.useJSONP){var b=new OpenLayers.Protocol.Script({url:this.url,
2885 callback:function(a){this.isLoading=!1;this.events.triggerEvent("loadend");this.json=a.data},scope:this});b.read();this.request=b}else this.request=OpenLayers.Request.GET({url:this.url,callback:function(a){this.isLoading=!1;this.events.triggerEvent("loadend");200===a.status&&this.parseData(a.responseText)},scope:this});else this.unload();return a},abortLoading:function(){this.request&&(this.request.abort(),delete this.request);this.isLoading=!1},getFeatureInfo:function(a,b){var c=null;if(this.json){var d=
2886 this.getFeatureId(a,b);null!==d&&(c={id:d,data:this.json.data[d]})}return c},getFeatureId:function(a,b){var c=null;if(this.json){var d=this.utfgridResolution,d=this.json.grid[Math.floor(b/d)].charCodeAt(Math.floor(a/d)),d=this.indexFromCharCode(d),e=this.json.keys;!isNaN(d)&&d in e&&(c=e[d])}return c},indexFromCharCode:function(a){93<=a&&a--;35<=a&&a--;return a-32},parseData:function(a){this.format||(this.format=new OpenLayers.Format.JSON);this.json=this.format.read(a)},clear:function(){this.json=
2887 null},CLASS_NAME:"OpenLayers.Tile.UTFGrid"});OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:!1,updateWithPOST:!1,deleteWithPOST:!1,wildcarded:!1,srsInBBOX:!1,initialize:function(a){a=a||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var b=new OpenLayers.Format.QueryStringFilter({wildcarded:this.wildcarded,srsInBBOX:this.srsInBBOX});this.filterToParams=
2888 function(a,d){return b.write(a,d)}}},destroy:function(){this.headers=this.params=null;OpenLayers.Protocol.prototype.destroy.apply(this)},read:function(a){OpenLayers.Protocol.prototype.read.apply(this,arguments);a=a||{};a.params=OpenLayers.Util.applyDefaults(a.params,this.options.params);a=OpenLayers.Util.applyDefaults(a,this.options);a.filter&&this.filterToParams&&(a.params=this.filterToParams(a.filter,a.params));var b=void 0!==a.readWithPOST?a.readWithPOST:this.readWithPOST,c=new OpenLayers.Protocol.Response({requestType:"read"});
2889 b?(b=a.headers||{},b["Content-Type"]="application/x-www-form-urlencoded",c.priv=OpenLayers.Request.POST({url:a.url,callback:this.createCallback(this.handleRead,c,a),data:OpenLayers.Util.getParameterString(a.params),headers:b})):c.priv=OpenLayers.Request.GET({url:a.url,callback:this.createCallback(this.handleRead,c,a),params:a.params,headers:a.headers});return c},handleRead:function(a,b){this.handleResponse(a,b)},create:function(a,b){b=OpenLayers.Util.applyDefaults(b,this.options);var c=new OpenLayers.Protocol.Response({reqFeatures:a,
2890 requestType:"create"});c.priv=OpenLayers.Request.POST({url:b.url,callback:this.createCallback(this.handleCreate,c,b),headers:b.headers,data:this.format.write(a)});return c},handleCreate:function(a,b){this.handleResponse(a,b)},update:function(a,b){b=b||{};var c=b.url||a.url||this.options.url+"/"+a.fid;b=OpenLayers.Util.applyDefaults(b,this.options);var d=new OpenLayers.Protocol.Response({reqFeatures:a,requestType:"update"});d.priv=OpenLayers.Request[this.updateWithPOST?"POST":"PUT"]({url:c,callback:this.createCallback(this.handleUpdate,
2891 d,b),headers:b.headers,data:this.format.write(a)});return d},handleUpdate:function(a,b){this.handleResponse(a,b)},"delete":function(a,b){b=b||{};var c=b.url||a.url||this.options.url+"/"+a.fid;b=OpenLayers.Util.applyDefaults(b,this.options);var d=new OpenLayers.Protocol.Response({reqFeatures:a,requestType:"delete"}),e=this.deleteWithPOST?"POST":"DELETE",c={url:c,callback:this.createCallback(this.handleDelete,d,b),headers:b.headers};this.deleteWithPOST&&(c.data=this.format.write(a));d.priv=OpenLayers.Request[e](c);
2892 return d},handleDelete:function(a,b){this.handleResponse(a,b)},handleResponse:function(a,b){var c=a.priv;b.callback&&(200<=c.status&&300>c.status?("delete"!=a.requestType&&(a.features=this.parseFeatures(c)),a.code=OpenLayers.Protocol.Response.SUCCESS):a.code=OpenLayers.Protocol.Response.FAILURE,b.callback.call(b.scope,a))},parseFeatures:function(a){var b=a.responseXML;b&&b.documentElement||(b=a.responseText);return!b||0>=b.length?null:this.format.read(b)},commit:function(a,b){function c(a){for(var b=
2893 a.features?a.features.length:0,c=Array(b),e=0;e<b;++e)c[e]=a.features[e].fid;r.insertIds=c;d.apply(this,[a])}function d(a){this.callUserCallback(a,b);q=q&&a.success();f++;f>=p&&b.callback&&(r.code=q?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE,b.callback.apply(b.scope,[r]))}b=OpenLayers.Util.applyDefaults(b,this.options);var e=[],f=0,g={};g[OpenLayers.State.INSERT]=[];g[OpenLayers.State.UPDATE]=[];g[OpenLayers.State.DELETE]=[];for(var h,k,l=[],m=0,n=a.length;m<n;++m)if(h=
2894 a[m],k=g[h.state])k.push(h),l.push(h);var p=(0<g[OpenLayers.State.INSERT].length?1:0)+g[OpenLayers.State.UPDATE].length+g[OpenLayers.State.DELETE].length,q=!0,r=new OpenLayers.Protocol.Response({reqFeatures:l});h=g[OpenLayers.State.INSERT];0<h.length&&e.push(this.create(h,OpenLayers.Util.applyDefaults({callback:c,scope:this},b.create)));h=g[OpenLayers.State.UPDATE];for(m=h.length-1;0<=m;--m)e.push(this.update(h[m],OpenLayers.Util.applyDefaults({callback:d,scope:this},b.update)));h=g[OpenLayers.State.DELETE];
2895 for(m=h.length-1;0<=m;--m)e.push(this["delete"](h[m],OpenLayers.Util.applyDefaults({callback:d,scope:this},b["delete"])));return e},abort:function(a){a&&a.priv.abort()},callUserCallback:function(a,b){var c=b[a.requestType];c&&c.callback&&c.callback.call(c.scope,a)},CLASS_NAME:"OpenLayers.Protocol.HTTP"});OpenLayers.Strategy.Cluster=OpenLayers.Class(OpenLayers.Strategy,{distance:20,threshold:null,features:null,clusters:null,clustering:!1,resolution:null,activate:function(){var a=OpenLayers.Strategy.prototype.activate.call(this);if(a)this.layer.events.on({beforefeaturesadded:this.cacheFeatures,featuresremoved:this.clearCache,moveend:this.cluster,scope:this});return a},deactivate:function(){var a=OpenLayers.Strategy.prototype.deactivate.call(this);a&&(this.clearCache(),this.layer.events.un({beforefeaturesadded:this.cacheFeatures,
2896 featuresremoved:this.clearCache,moveend:this.cluster,scope:this}));return a},cacheFeatures:function(a){var b=!0;this.clustering||(this.clearCache(),this.features=a.features,this.cluster(),b=!1);return b},clearCache:function(){this.clustering||(this.features=null)},cluster:function(a){if((!a||a.zoomChanged)&&this.features&&(a=this.layer.map.getResolution(),a!=this.resolution||!this.clustersExist())){this.resolution=a;a=[];for(var b,c,d,e=0;e<this.features.length;++e)if(b=this.features[e],b.geometry){c=
2897 !1;for(var f=a.length-1;0<=f;--f)if(d=a[f],this.shouldCluster(d,b)){this.addToCluster(d,b);c=!0;break}c||a.push(this.createCluster(this.features[e]))}this.clustering=!0;this.layer.removeAllFeatures();this.clustering=!1;if(0<a.length){if(1<this.threshold)for(b=a.slice(),a=[],e=0,d=b.length;e<d;++e)c=b[e],c.attributes.count<this.threshold?Array.prototype.push.apply(a,c.cluster):a.push(c);this.clustering=!0;this.layer.addFeatures(a);this.clustering=!1}this.clusters=a}},clustersExist:function(){var a=
2898 !1;if(this.clusters&&0<this.clusters.length&&this.clusters.length==this.layer.features.length)for(var a=!0,b=0;b<this.clusters.length;++b)if(this.clusters[b]!=this.layer.features[b]){a=!1;break}return a},shouldCluster:function(a,b){var c=a.geometry.getBounds().getCenterLonLat(),d=b.geometry.getBounds().getCenterLonLat();return Math.sqrt(Math.pow(c.lon-d.lon,2)+Math.pow(c.lat-d.lat,2))/this.resolution<=this.distance},addToCluster:function(a,b){a.cluster.push(b);a.attributes.count+=1},createCluster:function(a){var b=
2899 a.geometry.getBounds().getCenterLonLat(),b=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(b.lon,b.lat),{count:1});b.cluster=[a];return b},CLASS_NAME:"OpenLayers.Strategy.Cluster"});OpenLayers.Strategy.Filter=OpenLayers.Class(OpenLayers.Strategy,{filter:null,cache:null,caching:!1,activate:function(){var a=OpenLayers.Strategy.prototype.activate.apply(this,arguments);a&&(this.cache=[],this.layer.events.on({beforefeaturesadded:this.handleAdd,beforefeaturesremoved:this.handleRemove,scope:this}));return a},deactivate:function(){this.cache=null;this.layer&&this.layer.events&&this.layer.events.un({beforefeaturesadded:this.handleAdd,beforefeaturesremoved:this.handleRemove,scope:this});
2900 return OpenLayers.Strategy.prototype.deactivate.apply(this,arguments)},handleAdd:function(a){if(!this.caching&&this.filter){var b=a.features;a.features=[];for(var c,d=0,e=b.length;d<e;++d)c=b[d],this.filter.evaluate(c)?a.features.push(c):this.cache.push(c)}},handleRemove:function(a){this.caching||(this.cache=[])},setFilter:function(a){this.filter=a;a=this.cache;this.cache=[];this.handleAdd({features:this.layer.features});0<this.cache.length&&(this.caching=!0,this.layer.removeFeatures(this.cache.slice()),
2901 this.caching=!1);0<a.length&&(a={features:a},this.handleAdd(a),0<a.features.length&&(this.caching=!0,this.layer.addFeatures(a.features),this.caching=!1))},CLASS_NAME:"OpenLayers.Strategy.Filter"});OpenLayers.Protocol.SOS=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Protocol.SOS.DEFAULTS);var b=OpenLayers.Protocol.SOS["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported SOS version: "+a.version;return new b(a)};OpenLayers.Protocol.SOS.DEFAULTS={version:"1.0.0"};OpenLayers.Format.WFSDescribeFeatureType=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:/^\s*|\s*$/g},namespaces:{xsd:"http://www.w3.org/2001/XMLSchema"},readers:{xsd:{schema:function(a,b){var c=[],d={},e,f;this.readChildNodes(a,{complexTypes:c,customTypes:d});var g=a.attributes,h,k;e=0;for(f=g.length;e<f;++e)h=g[e],k=h.name,0===k.indexOf("xmlns")?this.setNamespace(k.split(":")[1]||"",h.value):b[k]=h.value;b.featureTypes=c;b.targetPrefix=this.namespaceAlias[b.targetNamespace];e=0;for(f=
2902 c.length;e<f;++e)g=c[e],h=d[g.typeName],d[g.typeName]&&(g.typeName=h.name)},complexType:function(a,b){var c={typeName:a.getAttribute("name")};this.readChildNodes(a,c);b.complexTypes.push(c)},complexContent:function(a,b){this.readChildNodes(a,b)},extension:function(a,b){this.readChildNodes(a,b)},sequence:function(a,b){var c={elements:[]};this.readChildNodes(a,c);b.properties=c.elements},element:function(a,b){var c;if(b.elements){var d={};c=a.attributes;for(var e,f=0,g=c.length;f<g;++f)e=c[f],d[e.name]=
2903 e.value;c=d.type;c||(c={},this.readChildNodes(a,c),d.restriction=c,d.type=c.base);d.localType=(c.base||c).split(":").pop();b.elements.push(d);this.readChildNodes(a,d)}b.complexTypes&&(c=a.getAttribute("type"),d=c.split(":").pop(),b.customTypes[d]={name:a.getAttribute("name"),type:c})},annotation:function(a,b){b.annotation={};this.readChildNodes(a,b.annotation)},appinfo:function(a,b){b.appinfo||(b.appinfo=[]);b.appinfo.push(this.getChildValue(a))},documentation:function(a,b){b.documentation||(b.documentation=
2904 []);var c=this.getChildValue(a);b.documentation.push({lang:a.getAttribute("xml:lang"),textContent:c.replace(this.regExes.trimSpace,"")})},simpleType:function(a,b){this.readChildNodes(a,b)},restriction:function(a,b){b.base=a.getAttribute("base");this.readRestriction(a,b)}}},readRestriction:function(a,b){for(var c=a.childNodes,d,e,f=0,g=c.length;f<g;++f)d=c[f],1==d.nodeType&&(e=d.nodeName.split(":").pop(),d=d.getAttribute("value"),b[e]?("string"==typeof b[e]&&(b[e]=[b[e]]),b[e].push(d)):b[e]=d)},read:function(a){"string"==
2905 typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};if("ExceptionReport"===a.nodeName.split(":").pop()){var c=new OpenLayers.Format.OGCExceptionReport;b.error=c.read(a)}else this.readNode(a,b);return b},CLASS_NAME:"OpenLayers.Format.WFSDescribeFeatureType"});OpenLayers.Format.GeoRSS=OpenLayers.Class(OpenLayers.Format.XML,{rssns:"http://backend.userland.com/rss2",featureNS:"http://mapserver.gis.umn.edu/mapserver",georssns:"http://www.georss.org/georss",geons:"http://www.w3.org/2003/01/geo/wgs84_pos#",featureTitle:"Untitled",featureDescription:"No Description",gmlParser:null,xy:!1,createGeometryFromItem:function(a){var b=this.getElementsByTagNameNS(a,this.georssns,"point"),c=this.getElementsByTagNameNS(a,this.geons,"lat"),d=this.getElementsByTagNameNS(a,
2906 this.geons,"long"),e=this.getElementsByTagNameNS(a,this.georssns,"line"),f=this.getElementsByTagNameNS(a,this.georssns,"polygon"),g=this.getElementsByTagNameNS(a,this.georssns,"where");a=this.getElementsByTagNameNS(a,this.georssns,"box");if(0<b.length||0<c.length&&0<d.length){0<b.length?(c=OpenLayers.String.trim(b[0].firstChild.nodeValue).split(/\s+/),2!=c.length&&(c=OpenLayers.String.trim(b[0].firstChild.nodeValue).split(/\s*,\s*/))):c=[parseFloat(c[0].firstChild.nodeValue),parseFloat(d[0].firstChild.nodeValue)];
2907 var h=new OpenLayers.Geometry.Point(c[1],c[0])}else if(0<e.length){c=OpenLayers.String.trim(this.getChildValue(e[0])).split(/\s+/);d=[];e=0;for(f=c.length;e<f;e+=2)b=new OpenLayers.Geometry.Point(c[e+1],c[e]),d.push(b);h=new OpenLayers.Geometry.LineString(d)}else if(0<f.length){c=OpenLayers.String.trim(this.getChildValue(f[0])).split(/\s+/);d=[];e=0;for(f=c.length;e<f;e+=2)b=new OpenLayers.Geometry.Point(c[e+1],c[e]),d.push(b);h=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(d)])}else 0<
2908 g.length?(this.gmlParser||(this.gmlParser=new OpenLayers.Format.GML({xy:this.xy})),h=this.gmlParser.parseFeature(g[0]).geometry):0<a.length&&(c=OpenLayers.String.trim(a[0].firstChild.nodeValue).split(/\s+/),d=[],3<c.length&&(b=new OpenLayers.Geometry.Point(c[1],c[0]),d.push(b),b=new OpenLayers.Geometry.Point(c[1],c[2]),d.push(b),b=new OpenLayers.Geometry.Point(c[3],c[2]),d.push(b),b=new OpenLayers.Geometry.Point(c[3],c[0]),d.push(b),b=new OpenLayers.Geometry.Point(c[1],c[0]),d.push(b)),h=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(d)]));
2909 h&&(this.internalProjection&&this.externalProjection)&&h.transform(this.externalProjection,this.internalProjection);return h},createFeatureFromItem:function(a){var b=this.createGeometryFromItem(a),c=this._getChildValue(a,"*","title",this.featureTitle),d=this._getChildValue(a,"*","description",this._getChildValue(a,"*","content",this._getChildValue(a,"*","summary",this.featureDescription))),e=this._getChildValue(a,"*","link");if(!e)try{e=this.getElementsByTagNameNS(a,"*","link")[0].getAttribute("href")}catch(f){e=
2910 null}a=this._getChildValue(a,"*","id",null);b=new OpenLayers.Feature.Vector(b,{title:c,description:d,link:e});b.fid=a;return b},_getChildValue:function(a,b,c,d){return(a=this.getElementsByTagNameNS(a,b,c))&&a[0]&&a[0].firstChild&&a[0].firstChild.nodeValue?this.getChildValue(a[0]):void 0==d?"":d},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=null,b=this.getElementsByTagNameNS(a,"*","item");0==b.length&&(b=this.getElementsByTagNameNS(a,"*","entry"));
2911 a=b.length;for(var c=Array(a),d=0;d<a;d++)c[d]=this.createFeatureFromItem(b[d]);return c},write:function(a){var b;if(OpenLayers.Util.isArray(a)){b=this.createElementNS(this.rssns,"rss");for(var c=0,d=a.length;c<d;c++)b.appendChild(this.createFeatureXML(a[c]))}else b=this.createFeatureXML(a);return OpenLayers.Format.XML.prototype.write.apply(this,[b])},createFeatureXML:function(a){var b=this.buildGeometryNode(a.geometry),c=this.createElementNS(this.rssns,"item"),d=this.createElementNS(this.rssns,"title");
2912 d.appendChild(this.createTextNode(a.attributes.title?a.attributes.title:""));var e=this.createElementNS(this.rssns,"description");e.appendChild(this.createTextNode(a.attributes.description?a.attributes.description:""));c.appendChild(d);c.appendChild(e);a.attributes.link&&(d=this.createElementNS(this.rssns,"link"),d.appendChild(this.createTextNode(a.attributes.link)),c.appendChild(d));for(var f in a.attributes)"link"!=f&&("title"!=f&&"description"!=f)&&(d=this.createTextNode(a.attributes[f]),e=f,-1!=
2913 f.search(":")&&(e=f.split(":")[1]),e=this.createElementNS(this.featureNS,"feature:"+e),e.appendChild(d),c.appendChild(e));c.appendChild(b);return c},buildGeometryNode:function(a){this.internalProjection&&this.externalProjection&&(a=a.clone(),a.transform(this.internalProjection,this.externalProjection));var b;if("OpenLayers.Geometry.Polygon"==a.CLASS_NAME)b=this.createElementNS(this.georssns,"georss:polygon"),b.appendChild(this.buildCoordinatesNode(a.components[0]));else if("OpenLayers.Geometry.LineString"==
2914 a.CLASS_NAME)b=this.createElementNS(this.georssns,"georss:line"),b.appendChild(this.buildCoordinatesNode(a));else if("OpenLayers.Geometry.Point"==a.CLASS_NAME)b=this.createElementNS(this.georssns,"georss:point"),b.appendChild(this.buildCoordinatesNode(a));else throw"Couldn't parse "+a.CLASS_NAME;return b},buildCoordinatesNode:function(a){var b=null;a.components&&(b=a.components);if(b){a=b.length;for(var c=Array(a),d=0;d<a;d++)c[d]=b[d].y+" "+b[d].x;b=c.join(" ")}else b=a.y+" "+a.x;return this.createTextNode(b)},
2915 CLASS_NAME:"OpenLayers.Format.GeoRSS"});OpenLayers.Format.WPSCapabilities=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.WPSCapabilities"});OpenLayers.Format.WPSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows/1.1",wps:"http://www.opengis.net/wps/1.0.0",xlink:"http://www.w3.org/1999/xlink"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);
2916 var b={};this.readNode(a,b);return b},readers:{wps:{Capabilities:function(a,b){this.readChildNodes(a,b)},ProcessOfferings:function(a,b){b.processOfferings={};this.readChildNodes(a,b.processOfferings)},Process:function(a,b){var c={processVersion:this.getAttributeNS(a,this.namespaces.wps,"processVersion")};this.readChildNodes(a,c);b[c.identifier]=c},Languages:function(a,b){b.languages=[];this.readChildNodes(a,b.languages)},Default:function(a,b){var c={isDefault:!0};this.readChildNodes(a,c);b.push(c)},
2917 Supported:function(a,b){var c={};this.readChildNodes(a,c);b.push(c)}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WPSCapabilities.v1_0_0"});OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,pinchOrigin:null,currentCenter:null,autoActivate:!0,preserveCenter:!1,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions)},pinchStart:function(a,b){var c=this.preserveCenter?this.map.getPixelFromLonLat(this.map.getCenter()):a.xy;this.currentCenter=
2918 this.pinchOrigin=c},pinchMove:function(a,b){var c=b.scale,d=this.map.layerContainerOriginPx,e=this.pinchOrigin,f=this.preserveCenter?this.map.getPixelFromLonLat(this.map.getCenter()):a.xy,g=Math.round(d.x+f.x-e.x+(c-1)*(d.x-e.x)),d=Math.round(d.y+f.y-e.y+(c-1)*(d.y-e.y));this.map.applyTransform(g,d,c);this.currentCenter=f},pinchDone:function(a,b,c){this.map.applyTransform();a=this.map.getZoomForResolution(this.map.getResolution()/c.scale,!0);if(a!==this.map.getZoom()||!this.currentCenter.equals(this.pinchOrigin)){b=
2919 this.map.getResolutionForZoom(a);c=this.map.getLonLatFromPixel(this.pinchOrigin);var d=this.currentCenter,e=this.map.getSize();c.lon+=b*(e.w/2-d.x);c.lat-=b*(e.h/2-d.y);this.map.div.clientWidth=this.map.div.clientWidth;this.map.setCenter(c,a)}},CLASS_NAME:"OpenLayers.Control.PinchZoom"});OpenLayers.Control.TouchNavigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,pinchZoom:null,pinchZoomOptions:null,clickHandlerOptions:null,documentDrag:!1,autoActivate:!0,initialize:function(a){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments)},destroy:function(){this.deactivate();this.dragPan&&this.dragPan.destroy();this.dragPan=null;this.pinchZoom&&(this.pinchZoom.destroy(),delete this.pinchZoom);OpenLayers.Control.prototype.destroy.apply(this,
2920 arguments)},activate:function(){return OpenLayers.Control.prototype.activate.apply(this,arguments)?(this.dragPan.activate(),this.handlers.click.activate(),this.pinchZoom.activate(),!0):!1},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments)?(this.dragPan.deactivate(),this.handlers.click.deactivate(),this.pinchZoom.deactivate(),!0):!1},draw:function(){var a={click:this.defaultClick,dblclick:this.defaultDblClick},b=OpenLayers.Util.extend({"double":!0,stopDouble:!0,
2921 pixelTolerance:2},this.clickHandlerOptions);this.handlers.click=new OpenLayers.Handler.Click(this,a,b);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,documentDrag:this.documentDrag},this.dragPanOptions));this.dragPan.draw();this.pinchZoom=new OpenLayers.Control.PinchZoom(OpenLayers.Util.extend({map:this.map},this.pinchZoomOptions))},defaultClick:function(a){a.lastTouches&&2==a.lastTouches.length&&this.map.zoomOut()},defaultDblClick:function(a){this.map.zoomTo(this.map.zoom+
2922 1,a.xy)},CLASS_NAME:"OpenLayers.Control.TouchNavigation"});OpenLayers.Console.warn("OpenLayers.Rico is deprecated");OpenLayers.Rico=OpenLayers.Rico||{};
2923 OpenLayers.Rico.Color=OpenLayers.Class({initialize:function(a,b,c){this.rgb={r:a,g:b,b:c}},setRed:function(a){this.rgb.r=a},setGreen:function(a){this.rgb.g=a},setBlue:function(a){this.rgb.b=a},setHue:function(a){var b=this.asHSB();b.h=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},setSaturation:function(a){var b=this.asHSB();b.s=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},setBrightness:function(a){var b=this.asHSB();b.b=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},
2924 darken:function(a){var b=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,Math.max(b.b-a,0))},brighten:function(a){var b=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,Math.min(b.b+a,1))},blend:function(a){this.rgb.r=Math.floor((this.rgb.r+a.rgb.r)/2);this.rgb.g=Math.floor((this.rgb.g+a.rgb.g)/2);this.rgb.b=Math.floor((this.rgb.b+a.rgb.b)/2)},isBright:function(){this.asHSB();return 0.5<this.asHSB().b},isDark:function(){return!this.isBright()},asRGB:function(){return"rgb("+
2925 this.rgb.r+","+this.rgb.g+","+this.rgb.b+")"},asHex:function(){return"#"+this.rgb.r.toColorPart()+this.rgb.g.toColorPart()+this.rgb.b.toColorPart()},asHSB:function(){return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r,this.rgb.g,this.rgb.b)},toString:function(){return this.asHex()}});
2926 OpenLayers.Rico.Color.createFromHex=function(a){if(4==a.length){var b=a;a="#";for(var c=1;4>c;c++)a+=b.charAt(c)+b.charAt(c)}0==a.indexOf("#")&&(a=a.substring(1));b=a.substring(0,2);c=a.substring(2,4);a=a.substring(4,6);return new OpenLayers.Rico.Color(parseInt(b,16),parseInt(c,16),parseInt(a,16))};
2927 OpenLayers.Rico.Color.createColorFromBackground=function(a){var b=OpenLayers.Element.getStyle(OpenLayers.Util.getElement(a),"backgroundColor");return"transparent"==b&&a.parentNode?OpenLayers.Rico.Color.createColorFromBackground(a.parentNode):null==b?new OpenLayers.Rico.Color(255,255,255):0==b.indexOf("rgb(")?(a=b.substring(4,b.length-1).split(","),new OpenLayers.Rico.Color(parseInt(a[0]),parseInt(a[1]),parseInt(a[2]))):0==b.indexOf("#")?OpenLayers.Rico.Color.createFromHex(b):new OpenLayers.Rico.Color(255,
2928 255,255)};
2929 OpenLayers.Rico.Color.HSBtoRGB=function(a,b,c){var d=0,e=0,f=0;if(0==b)f=e=d=parseInt(255*c+0.5);else{a=6*(a-Math.floor(a));var g=a-Math.floor(a),h=c*(1-b),k=c*(1-b*g);b=c*(1-b*(1-g));switch(parseInt(a)){case 0:d=255*c+0.5;e=255*b+0.5;f=255*h+0.5;break;case 1:d=255*k+0.5;e=255*c+0.5;f=255*h+0.5;break;case 2:d=255*h+0.5;e=255*c+0.5;f=255*b+0.5;break;case 3:d=255*h+0.5;e=255*k+0.5;f=255*c+0.5;break;case 4:d=255*b+0.5;e=255*h+0.5;f=255*c+0.5;break;case 5:d=255*c+0.5,e=255*h+0.5,f=255*k+0.5}}return{r:parseInt(d),g:parseInt(e),
2930 b:parseInt(f)}};OpenLayers.Rico.Color.RGBtoHSB=function(a,b,c){var d,e=a>b?a:b;c>e&&(e=c);var f=a<b?a:b;c<f&&(f=c);d=0!=e?(e-f)/e:0;if(0==d)a=0;else{var g=(e-a)/(e-f),h=(e-b)/(e-f);c=(e-c)/(e-f);a=(a==e?c-h:b==e?2+g-c:4+h-g)/6;0>a&&(a+=1)}return{h:a,s:d,b:e/255}};OpenLayers.Style2=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:!1,rules:null,initialize:function(a){OpenLayers.Util.extend(this,a);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){for(var a=0,b=this.rules.length;a<b;a++)this.rules[a].destroy();delete this.rules},clone:function(){var a=OpenLayers.Util.extend({},this);if(this.rules){a.rules=[];for(var b=0,c=this.rules.length;b<c;++b)a.rules.push(this.rules[b].clone())}return new OpenLayers.Style2(a)},
2931 CLASS_NAME:"OpenLayers.Style2"});OpenLayers.Format.WFS=OpenLayers.Class(OpenLayers.Format.GML,{layer:null,wfsns:"http://www.opengis.net/wfs",ogcns:"http://www.opengis.net/ogc",initialize:function(a,b){OpenLayers.Format.GML.prototype.initialize.apply(this,[a]);this.layer=b;this.layer.featureNS&&(this.featureNS=this.layer.featureNS);this.layer.options.geometry_column&&(this.geometryName=this.layer.options.geometry_column);this.layer.options.typename&&(this.featureName=this.layer.options.typename)},write:function(a){var b=this.createElementNS(this.wfsns,
2932 "wfs:Transaction");b.setAttribute("version","1.0.0");b.setAttribute("service","WFS");for(var c=0;c<a.length;c++)switch(a[c].state){case OpenLayers.State.INSERT:b.appendChild(this.insert(a[c]));break;case OpenLayers.State.UPDATE:b.appendChild(this.update(a[c]));break;case OpenLayers.State.DELETE:b.appendChild(this.remove(a[c]))}return OpenLayers.Format.XML.prototype.write.apply(this,[b])},createFeatureXML:function(a){var b=this.buildGeometryNode(a.geometry),c=this.createElementNS(this.featureNS,"feature:"+
2933 this.geometryName);c.appendChild(b);b=this.createElementNS(this.featureNS,"feature:"+this.featureName);b.appendChild(c);for(var d in a.attributes){var c=this.createTextNode(a.attributes[d]),e=d;-1!=d.search(":")&&(e=d.split(":")[1]);e=this.createElementNS(this.featureNS,"feature:"+e);e.appendChild(c);b.appendChild(e)}return b},insert:function(a){var b=this.createElementNS(this.wfsns,"wfs:Insert");b.appendChild(this.createFeatureXML(a));return b},update:function(a){a.fid||OpenLayers.Console.userError(OpenLayers.i18n("noFID"));
2934 var b=this.createElementNS(this.wfsns,"wfs:Update");b.setAttribute("typeName",this.featurePrefix+":"+this.featureName);b.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var c=this.createElementNS(this.wfsns,"wfs:Property"),d=this.createElementNS(this.wfsns,"wfs:Name"),e=this.createTextNode(this.geometryName);d.appendChild(e);c.appendChild(d);d=this.createElementNS(this.wfsns,"wfs:Value");e=this.buildGeometryNode(a.geometry);a.layer&&e.setAttribute("srsName",a.layer.projection.getCode());
2935 d.appendChild(e);c.appendChild(d);b.appendChild(c);for(var f in a.attributes)c=this.createElementNS(this.wfsns,"wfs:Property"),d=this.createElementNS(this.wfsns,"wfs:Name"),d.appendChild(this.createTextNode(f)),c.appendChild(d),d=this.createElementNS(this.wfsns,"wfs:Value"),d.appendChild(this.createTextNode(a.attributes[f])),c.appendChild(d),b.appendChild(c);c=this.createElementNS(this.ogcns,"ogc:Filter");f=this.createElementNS(this.ogcns,"ogc:FeatureId");f.setAttribute("fid",a.fid);c.appendChild(f);
2936 b.appendChild(c);return b},remove:function(a){if(!a.fid)return OpenLayers.Console.userError(OpenLayers.i18n("noFID")),!1;var b=this.createElementNS(this.wfsns,"wfs:Delete");b.setAttribute("typeName",this.featurePrefix+":"+this.featureName);b.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var c=this.createElementNS(this.ogcns,"ogc:Filter"),d=this.createElementNS(this.ogcns,"ogc:FeatureId");d.setAttribute("fid",a.fid);c.appendChild(d);b.appendChild(c);return b},destroy:function(){this.layer=
2937 null},CLASS_NAME:"OpenLayers.Format.WFS"});OpenLayers.Format.SLD.v1_0_0_GeoServer=OpenLayers.Class(OpenLayers.Format.SLD.v1_0_0,{version:"1.0.0",profile:"GeoServer",readers:OpenLayers.Util.applyDefaults({sld:OpenLayers.Util.applyDefaults({Priority:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.priority=c)},VendorOption:function(a,b){b.vendorOptions||(b.vendorOptions={});b.vendorOptions[a.getAttribute("name")]=this.getChildValue(a)},TextSymbolizer:function(a,b){OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld.TextSymbolizer.apply(this,
2938 arguments);var c=this.multipleSymbolizers?b.symbolizers[b.symbolizers.length-1]:b.symbolizer.Text;void 0===c.graphic&&(c.graphic=!1)}},OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld)},OpenLayers.Format.SLD.v1_0_0.prototype.readers),writers:OpenLayers.Util.applyDefaults({sld:OpenLayers.Util.applyDefaults({Priority:function(a){return this.writers.sld._OGCExpression.call(this,"sld:Priority",a)},VendorOption:function(a){return this.createElementNSPlus("sld:VendorOption",{attributes:{name:a.name},
2939 value:a.value})},TextSymbolizer:function(a){var b=OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld.TextSymbolizer.apply(this,arguments);!1!==a.graphic&&(a.externalGraphic||a.graphicName)&&this.writeNode("Graphic",a,b);"priority"in a&&this.writeNode("Priority",a.priority,b);return this.addVendorOptions(b,a)},PointSymbolizer:function(a){var b=OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld.PointSymbolizer.apply(this,arguments);return this.addVendorOptions(b,a)},LineSymbolizer:function(a){var b=
2940 OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld.LineSymbolizer.apply(this,arguments);return this.addVendorOptions(b,a)},PolygonSymbolizer:function(a){var b=OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld.PolygonSymbolizer.apply(this,arguments);return this.addVendorOptions(b,a)}},OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld)},OpenLayers.Format.SLD.v1_0_0.prototype.writers),addVendorOptions:function(a,b){if(b.vendorOptions)for(var c in b.vendorOptions)this.writeNode("VendorOption",{name:c,
2941 value:b.vendorOptions[c]},a);return a},CLASS_NAME:"OpenLayers.Format.SLD.v1_0_0_GeoServer"});OpenLayers.Layer.Boxes=OpenLayers.Class(OpenLayers.Layer.Markers,{drawMarker:function(a){var b=this.map.getLayerPxFromLonLat({lon:a.bounds.left,lat:a.bounds.top}),c=this.map.getLayerPxFromLonLat({lon:a.bounds.right,lat:a.bounds.bottom});null==c||null==b?a.display(!1):(b=a.draw(b,{w:Math.max(1,c.x-b.x),h:Math.max(1,c.y-b.y)}),a.drawn||(this.div.appendChild(b),a.drawn=!0))},removeMarker:function(a){OpenLayers.Util.removeItem(this.markers,a);null!=a.div&&a.div.parentNode==this.div&&this.div.removeChild(a.div)},
2942 CLASS_NAME:"OpenLayers.Layer.Boxes"});OpenLayers.Format.WFSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{readers:{wfs:OpenLayers.Util.applyDefaults({Service:function(a,b){b.service={};this.readChildNodes(a,b.service)},Fees:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.fees=c)},AccessConstraints:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.accessConstraints=c)},OnlineResource:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.onlineResource=
2943 c)},Keywords:function(a,b){var c=this.getChildValue(a);c&&"none"!=c.toLowerCase()&&(b.keywords=c.split(", "))},Capability:function(a,b){b.capability={};this.readChildNodes(a,b.capability)},Request:function(a,b){b.request={};this.readChildNodes(a,b.request)},GetFeature:function(a,b){b.getfeature={href:{},formats:[]};this.readChildNodes(a,b.getfeature)},ResultFormat:function(a,b){for(var c=a.childNodes,d,e=0;e<c.length;e++)d=c[e],1==d.nodeType&&b.formats.push(d.nodeName)},DCPType:function(a,b){this.readChildNodes(a,
2944 b)},HTTP:function(a,b){this.readChildNodes(a,b.href)},Get:function(a,b){b.get=a.getAttribute("onlineResource")},Post:function(a,b){b.post=a.getAttribute("onlineResource")},SRS:function(a,b){var c=this.getChildValue(a);c&&(b.srs=c)}},OpenLayers.Format.WFSCapabilities.v1.prototype.readers.wfs)},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_0_0"});OpenLayers.Format.WMSCapabilities.v1_3=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{wms:OpenLayers.Util.applyDefaults({WMS_Capabilities:function(a,b){this.readChildNodes(a,b)},LayerLimit:function(a,b){b.layerLimit=parseInt(this.getChildValue(a))},MaxWidth:function(a,b){b.maxWidth=parseInt(this.getChildValue(a))},MaxHeight:function(a,b){b.maxHeight=parseInt(this.getChildValue(a))},BoundingBox:function(a,b){var c=OpenLayers.Format.WMSCapabilities.v1.prototype.readers.wms.BoundingBox.apply(this,
2945 [a,b]);c.srs=a.getAttribute("CRS");b.bbox[c.srs]=c},CRS:function(a,b){this.readers.wms.SRS.apply(this,[a,b])},EX_GeographicBoundingBox:function(a,b){b.llbbox=[];this.readChildNodes(a,b.llbbox)},westBoundLongitude:function(a,b){b[0]=this.getChildValue(a)},eastBoundLongitude:function(a,b){b[2]=this.getChildValue(a)},southBoundLatitude:function(a,b){b[1]=this.getChildValue(a)},northBoundLatitude:function(a,b){b[3]=this.getChildValue(a)},MinScaleDenominator:function(a,b){b.maxScale=parseFloat(this.getChildValue(a)).toPrecision(16)},
2946 MaxScaleDenominator:function(a,b){b.minScale=parseFloat(this.getChildValue(a)).toPrecision(16)},Dimension:function(a,b){var c={name:a.getAttribute("name").toLowerCase(),units:a.getAttribute("units"),unitsymbol:a.getAttribute("unitSymbol"),nearestVal:"1"===a.getAttribute("nearestValue"),multipleVal:"1"===a.getAttribute("multipleValues"),"default":a.getAttribute("default")||"",current:"1"===a.getAttribute("current"),values:this.getChildValue(a).split(",")};b.dimensions[c.name]=c},Keyword:function(a,
2947 b){var c={value:this.getChildValue(a),vocabulary:a.getAttribute("vocabulary")};b.keywords&&b.keywords.push(c)}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers.wms),sld:{UserDefinedSymbolization:function(a,b){this.readers.wms.UserDefinedSymbolization.apply(this,[a,b]);b.userSymbols.inlineFeature=1==parseInt(a.getAttribute("InlineFeature"));b.userSymbols.remoteWCS=1==parseInt(a.getAttribute("RemoteWCS"))},DescribeLayer:function(a,b){this.readers.wms.DescribeLayer.apply(this,[a,b])},GetLegendGraphic:function(a,
2948 b){this.readers.wms.GetLegendGraphic.apply(this,[a,b])}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3"});OpenLayers.Layer.Zoomify=OpenLayers.Class(OpenLayers.Layer.Grid,{size:null,isBaseLayer:!0,standardTileSize:256,tileOriginCorner:"tl",numberOfTiers:0,tileCountUpToTier:null,tierSizeInTiles:null,tierImageSize:null,initialize:function(a,b,c,d){this.initializeZoomify(c);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a,b,c,{},d])},initializeZoomify:function(a){var b=a.clone();this.size=a.clone();a=new OpenLayers.Size(Math.ceil(b.w/this.standardTileSize),Math.ceil(b.h/this.standardTileSize));this.tierSizeInTiles=
2949 [a];for(this.tierImageSize=[b];b.w>this.standardTileSize||b.h>this.standardTileSize;)b=new OpenLayers.Size(Math.floor(b.w/2),Math.floor(b.h/2)),a=new OpenLayers.Size(Math.ceil(b.w/this.standardTileSize),Math.ceil(b.h/this.standardTileSize)),this.tierSizeInTiles.push(a),this.tierImageSize.push(b);this.tierSizeInTiles.reverse();this.tierImageSize.reverse();this.numberOfTiers=this.tierSizeInTiles.length;b=[1];this.tileCountUpToTier=[0];for(a=1;a<this.numberOfTiers;a++)b.unshift(Math.pow(2,a)),this.tileCountUpToTier.push(this.tierSizeInTiles[a-
2950 1].w*this.tierSizeInTiles[a-1].h+this.tileCountUpToTier[a-1]);this.serverResolutions||(this.serverResolutions=b)},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);this.tileCountUpToTier.length=0;this.tierSizeInTiles.length=0;this.tierImageSize.length=0},clone:function(a){null==a&&(a=new OpenLayers.Layer.Zoomify(this.name,this.url,this.size,this.options));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){a=this.adjustBounds(a);var b=
2951 this.getServerResolution(),c=Math.round((a.left-this.tileOrigin.lon)/(b*this.tileSize.w));a=Math.round((this.tileOrigin.lat-a.top)/(b*this.tileSize.h));b=this.getZoomForResolution(b);c="TileGroup"+Math.floor((c+a*this.tierSizeInTiles[b].w+this.tileCountUpToTier[b])/256)+"/"+b+"-"+c+"-"+a+".jpg";b=this.url;OpenLayers.Util.isArray(b)&&(b=this.selectUrl(c,b));return b+c},getImageSize:function(){if(0<arguments.length){var a=this.adjustBounds(arguments[0]),b=this.getServerResolution(),c=Math.round((a.left-
2952 this.tileOrigin.lon)/(b*this.tileSize.w)),a=Math.round((this.tileOrigin.lat-a.top)/(b*this.tileSize.h)),b=this.getZoomForResolution(b),d=this.standardTileSize,e=this.standardTileSize;c==this.tierSizeInTiles[b].w-1&&(d=this.tierImageSize[b].w%this.standardTileSize);a==this.tierSizeInTiles[b].h-1&&(e=this.tierImageSize[b].h%this.standardTileSize);return new OpenLayers.Size(d,e)}return this.tileSize},setMap:function(a){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,
2953 this.map.maxExtent.top)},CLASS_NAME:"OpenLayers.Layer.Zoomify"});OpenLayers.Layer.MapServer=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{mode:"map",map_imagetype:"png"},initialize:function(a,b,c,d){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);if(null==d||null==d.isBaseLayer)this.isBaseLayer="true"!=this.params.transparent&&!0!=this.params.transparent},clone:function(a){null==a&&(a=new OpenLayers.Layer.MapServer(this.name,this.url,this.params,this.getOptions()));
2954 return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){a=this.adjustBounds(a);a=[a.left,a.bottom,a.right,a.top];var b=this.getImageSize();return this.getFullRequestString({mapext:a,imgext:a,map_size:[b.w,b.h],imgx:b.w/2,imgy:b.h/2,imgxy:[b.w,b.h]})},getFullRequestString:function(a,b){var c=null==b?this.url:b,d=OpenLayers.Util.extend({},this.params),d=OpenLayers.Util.extend(d,a),e=OpenLayers.Util.getParameterString(d);OpenLayers.Util.isArray(c)&&(c=this.selectUrl(e,c));
2955 var e=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(c)),f;for(f in d)f.toUpperCase()in e&&delete d[f];e=OpenLayers.Util.getParameterString(d);d=c;e=e.replace(/,/g,"+");""!=e&&(f=c.charAt(c.length-1),d="&"==f||"?"==f?d+e:-1==c.indexOf("?")?d+("?"+e):d+("&"+e));return d},CLASS_NAME:"OpenLayers.Layer.MapServer"});OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(a){if(this.supported()){if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);for(var b=document.createStyleSheet(),c="shape rect oval fill stroke imagedata group textbox".split(" "),d=0,e=c.length;d<e;d++)b.addRule("olv\\:"+c[d],"behavior: url(#default#VML); position: absolute; display: inline-block;")}OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
2956 arguments)}},supported:function(){return!!document.namespaces},setExtent:function(a,b){var c=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments),d=this.getResolution(),e=a.left/d|0,d=a.top/d-this.size.h|0;b||!this.offset?(this.offset={x:e,y:d},d=e=0):(e-=this.offset.x,d-=this.offset.y);this.root.coordorigin=e-this.xOffset+" "+d;for(var e=[this.root,this.vectorRoot,this.textRoot],f=0,g=e.length;f<g;++f)d=e[f],d.coordsize=this.size.w+" "+this.size.h;this.root.style.flip="y";return c},
2957 setSize:function(a){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);for(var b=[this.rendererRoot,this.root,this.vectorRoot,this.textRoot],c=this.size.w+"px",d=this.size.h+"px",e,f=0,g=b.length;f<g;++f)e=b[f],e.style.width=c,e.style.height=d},getNodeType:function(a,b){var c=null;switch(a.CLASS_NAME){case "OpenLayers.Geometry.Point":c=b.externalGraphic?"olv:rect":this.isComplexSymbol(b.graphicName)?"olv:shape":"olv:oval";break;case "OpenLayers.Geometry.Rectangle":c="olv:rect";break;case "OpenLayers.Geometry.LineString":case "OpenLayers.Geometry.LinearRing":case "OpenLayers.Geometry.Polygon":case "OpenLayers.Geometry.Curve":c=
2958 "olv:shape"}return c},setStyle:function(a,b,c,d){b=b||a._style;c=c||a._options;var e=b.fillColor,f=b.title||b.graphicTitle;f&&(a.title=f);if("OpenLayers.Geometry.Point"===a._geometryClass)if(b.externalGraphic){c.isFilled=!0;var e=b.graphicWidth||b.graphicHeight,f=b.graphicHeight||b.graphicWidth,e=e?e:2*b.pointRadius,f=f?f:2*b.pointRadius,g=this.getResolution(),h=void 0!=b.graphicXOffset?b.graphicXOffset:-(0.5*e),k=void 0!=b.graphicYOffset?b.graphicYOffset:-(0.5*f);a.style.left=((d.x-this.featureDx)/
2959 g-this.offset.x+h|0)+"px";a.style.top=(d.y/g-this.offset.y-(k+f)|0)+"px";a.style.width=e+"px";a.style.height=f+"px";a.style.flip="y";e="none";c.isStroked=!1}else this.isComplexSymbol(b.graphicName)?(f=this.importSymbol(b.graphicName),a.path=f.path,a.coordorigin=f.left+","+f.bottom,f=f.size,a.coordsize=f+","+f,this.drawCircle(a,d,b.pointRadius),a.style.flip="y"):this.drawCircle(a,d,b.pointRadius);c.isFilled?a.fillcolor=e:a.filled="false";d=a.getElementsByTagName("fill");d=0==d.length?null:d[0];c.isFilled?
2960 (d||(d=this.createNode("olv:fill",a.id+"_fill")),d.opacity=b.fillOpacity,"OpenLayers.Geometry.Point"===a._geometryClass&&b.externalGraphic&&(b.graphicOpacity&&(d.opacity=b.graphicOpacity),d.src=b.externalGraphic,d.type="frame",b.graphicWidth&&b.graphicHeight||(d.aspect="atmost")),d.parentNode!=a&&a.appendChild(d)):d&&a.removeChild(d);e=b.rotation;if(void 0!==e||void 0!==a._rotation)a._rotation=e,b.externalGraphic?(this.graphicRotate(a,h,k,b),d.opacity=0):"OpenLayers.Geometry.Point"===a._geometryClass&&
2961 (a.style.rotation=e||0);h=a.getElementsByTagName("stroke");h=0==h.length?null:h[0];c.isStroked?(h||(h=this.createNode("olv:stroke",a.id+"_stroke"),a.appendChild(h)),h.on=!0,h.color=b.strokeColor,h.weight=b.strokeWidth+"px",h.opacity=b.strokeOpacity,h.endcap="butt"==b.strokeLinecap?"flat":b.strokeLinecap||"round",b.strokeDashstyle&&(h.dashstyle=this.dashStyle(b))):(a.stroked=!1,h&&(h.on=!1));"inherit"!=b.cursor&&null!=b.cursor&&(a.style.cursor=b.cursor);return a},graphicRotate:function(a,b,c,d){d=
2962 d||a._style;var e=d.rotation||0,f,g;if(d.graphicWidth&&d.graphicHeight){g=Math.max(d.graphicWidth,d.graphicHeight);f=d.graphicWidth/d.graphicHeight;var h=Math.round(d.graphicWidth||g*f),k=Math.round(d.graphicHeight||g);a.style.width=h+"px";a.style.height=k+"px";var l=document.getElementById(a.id+"_image");l||(l=this.createNode("olv:imagedata",a.id+"_image"),a.appendChild(l));l.style.width=h+"px";l.style.height=k+"px";l.src=d.externalGraphic;l.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='', sizingMethod='scale')";
2963 l=e*Math.PI/180;e=Math.sin(l);l=Math.cos(l);e="progid:DXImageTransform.Microsoft.Matrix(M11="+l+",M12="+-e+",M21="+e+",M22="+l+",SizingMethod='auto expand')\n";(l=d.graphicOpacity||d.fillOpacity)&&1!=l&&(e+="progid:DXImageTransform.Microsoft.BasicImage(opacity="+l+")\n");a.style.filter=e;e=new OpenLayers.Geometry.Point(-b,-c);h=(new OpenLayers.Bounds(0,0,h,k)).toGeometry();h.rotate(d.rotation,e);h=h.getBounds();a.style.left=Math.round(parseInt(a.style.left)+h.left)+"px";a.style.top=Math.round(parseInt(a.style.top)-
2964 h.bottom)+"px"}else{var m=new Image;m.onreadystatechange=OpenLayers.Function.bind(function(){if("complete"==m.readyState||"interactive"==m.readyState)f=m.width/m.height,g=Math.max(2*d.pointRadius,d.graphicWidth||0,d.graphicHeight||0),b*=f,d.graphicWidth=g*f,d.graphicHeight=g,this.graphicRotate(a,b,c,d)},this);m.src=d.externalGraphic}},postDraw:function(a){a.style.visibility="visible";var b=a._style.fillColor,c=a._style.strokeColor;"none"==b&&a.fillcolor!=b&&(a.fillcolor=b);"none"==c&&a.strokecolor!=
2965 c&&(a.strokecolor=c)},setNodeDimension:function(a,b){var c=b.getBounds();if(c){var d=this.getResolution(),c=new OpenLayers.Bounds((c.left-this.featureDx)/d-this.offset.x|0,c.bottom/d-this.offset.y|0,(c.right-this.featureDx)/d-this.offset.x|0,c.top/d-this.offset.y|0);a.style.left=c.left+"px";a.style.top=c.top+"px";a.style.width=c.getWidth()+"px";a.style.height=c.getHeight()+"px";a.coordorigin=c.left+" "+c.top;a.coordsize=c.getWidth()+" "+c.getHeight()}},dashStyle:function(a){a=a.strokeDashstyle;switch(a){case "solid":case "dot":case "dash":case "dashdot":case "longdash":case "longdashdot":return a;
2966 default:return a=a.split(/[ ,]/),2==a.length?1*a[0]>=2*a[1]?"longdash":1==a[0]||1==a[1]?"dot":"dash":4==a.length?1*a[0]>=2*a[1]?"longdashdot":"dashdot":"solid"}},createNode:function(a,b){var c=document.createElement(a);b&&(c.id=b);c.unselectable="on";c.onselectstart=OpenLayers.Function.False;return c},nodeTypeCompare:function(a,b){var c=b,d=c.indexOf(":");-1!=d&&(c=c.substr(d+1));var e=a.nodeName,d=e.indexOf(":");-1!=d&&(e=e.substr(d+1));return c==e},createRenderRoot:function(){return this.nodeFactory(this.container.id+
2967 "_vmlRoot","div")},createRoot:function(a){return this.nodeFactory(this.container.id+a,"olv:group")},drawPoint:function(a,b){return this.drawCircle(a,b,1)},drawCircle:function(a,b,c){if(!isNaN(b.x)&&!isNaN(b.y)){var d=this.getResolution();a.style.left=((b.x-this.featureDx)/d-this.offset.x|0)-c+"px";a.style.top=(b.y/d-this.offset.y|0)-c+"px";b=2*c;a.style.width=b+"px";a.style.height=b+"px";return a}return!1},drawLineString:function(a,b){return this.drawLine(a,b,!1)},drawLinearRing:function(a,b){return this.drawLine(a,
2968 b,!0)},drawLine:function(a,b,c){this.setNodeDimension(a,b);for(var d=this.getResolution(),e=b.components.length,f=Array(e),g,h,k=0;k<e;k++)g=b.components[k],h=(g.x-this.featureDx)/d-this.offset.x|0,g=g.y/d-this.offset.y|0,f[k]=" "+h+","+g+" l ";b=c?" x e":" e";a.path="m"+f.join("")+b;return a},drawPolygon:function(a,b){this.setNodeDimension(a,b);var c=this.getResolution(),d=[],e,f,g,h,k,l,m,n,p,q;e=0;for(f=b.components.length;e<f;e++){d.push("m");g=b.components[e].components;h=0===e;l=k=null;m=0;
2969 for(n=g.length;m<n;m++)p=g[m],q=(p.x-this.featureDx)/c-this.offset.x|0,p=p.y/c-this.offset.y|0,q=" "+q+","+p,d.push(q),0==m&&d.push(" l"),h||(k?k!=q&&(l?l!=q&&(h=!0):l=q):k=q);d.push(h?" x ":" ")}d.push("e");a.path=d.join("");return a},drawRectangle:function(a,b){var c=this.getResolution();a.style.left=((b.x-this.featureDx)/c-this.offset.x|0)+"px";a.style.top=(b.y/c-this.offset.y|0)+"px";a.style.width=(b.width/c|0)+"px";a.style.height=(b.height/c|0)+"px";return a},drawText:function(a,b,c){var d=this.nodeFactory(a+
2970 this.LABEL_ID_SUFFIX,"olv:rect"),e=this.nodeFactory(a+this.LABEL_ID_SUFFIX+"_textbox","olv:textbox"),f=this.getResolution();d.style.left=((c.x-this.featureDx)/f-this.offset.x|0)+"px";d.style.top=(c.y/f-this.offset.y|0)+"px";d.style.flip="y";e.innerText=b.label;"inherit"!=b.cursor&&null!=b.cursor&&(e.style.cursor=b.cursor);b.fontColor&&(e.style.color=b.fontColor);b.fontOpacity&&(e.style.filter="alpha(opacity="+100*b.fontOpacity+")");b.fontFamily&&(e.style.fontFamily=b.fontFamily);b.fontSize&&(e.style.fontSize=
2971 b.fontSize);b.fontWeight&&(e.style.fontWeight=b.fontWeight);b.fontStyle&&(e.style.fontStyle=b.fontStyle);!0===b.labelSelect&&(d._featureId=a,e._featureId=a,e._geometry=c,e._geometryClass=c.CLASS_NAME);e.style.whiteSpace="nowrap";e.inset="1px,0px,0px,0px";d.parentNode||(d.appendChild(e),this.textRoot.appendChild(d));b=b.labelAlign||"cm";1==b.length&&(b+="m");a=e.clientWidth*OpenLayers.Renderer.VML.LABEL_SHIFT[b.substr(0,1)];e=e.clientHeight*OpenLayers.Renderer.VML.LABEL_SHIFT[b.substr(1,1)];d.style.left=
2972 parseInt(d.style.left)-a-1+"px";d.style.top=parseInt(d.style.top)+e+"px"},moveRoot:function(a){var b=this.map.getLayer(a.container.id);b instanceof OpenLayers.Layer.Vector.RootContainer&&(b=this.map.getLayer(this.container.id));b&&b.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this,arguments);b&&b.redraw()},importSymbol:function(a){var b=this.container.id+"-"+a,c=this.symbolCache[b];if(c)return c;c=OpenLayers.Renderer.symbol[a];if(!c)throw Error(a+" is not a valid symbol name");
2973 a=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);for(var d=["m"],e=0;e<c.length;e+=2){var f=c[e],g=c[e+1];a.left=Math.min(a.left,f);a.bottom=Math.min(a.bottom,g);a.right=Math.max(a.right,f);a.top=Math.max(a.top,g);d.push(f);d.push(g);0==e&&d.push("l")}d.push("x e");c=d.join(" ");d=(a.getWidth()-a.getHeight())/2;0<d?(a.bottom-=d,a.top+=d):(a.left+=d,a.right-=d);c={path:c,size:a.getWidth(),left:a.left,bottom:a.bottom};return this.symbolCache[b]=c},CLASS_NAME:"OpenLayers.Renderer.VML"});
2974 OpenLayers.Renderer.VML.LABEL_SHIFT={l:0,c:0.5,r:1,t:0,m:0.5,b:1};OpenLayers.Control.CacheRead=OpenLayers.Class(OpenLayers.Control,{fetchEvent:"tileloadstart",layers:null,autoActivate:!0,setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);var b,c=this.layers||a.layers;for(b=c.length-1;0<=b;--b)this.addLayer({layer:c[b]});if(!this.layers)a.events.on({addlayer:this.addLayer,removeLayer:this.removeLayer,scope:this})},addLayer:function(a){a.layer.events.register(this.fetchEvent,this,this.fetch)},removeLayer:function(a){a.layer.events.unregister(this.fetchEvent,
2975 this,this.fetch)},fetch:function(a){if(this.active&&window.localStorage&&a.tile instanceof OpenLayers.Tile.Image){var b=a.tile,c=b.url;!b.layer.crossOriginKeyword&&(OpenLayers.ProxyHost&&0===c.indexOf(OpenLayers.ProxyHost))&&(c=OpenLayers.Control.CacheWrite.urlMap[c]);if(c=window.localStorage.getItem("olCache_"+c))b.url=c,"tileerror"===a.type&&b.setImgSrc(c)}},destroy:function(){if(this.layers||this.map){var a,b=this.layers||this.map.layers;for(a=b.length-1;0<=a;--a)this.removeLayer({layer:b[a]})}this.map&&
2976 this.map.events.un({addlayer:this.addLayer,removeLayer:this.removeLayer,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments)},CLASS_NAME:"OpenLayers.Control.CacheRead"});OpenLayers.Protocol.WFS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.0.0",CLASS_NAME:"OpenLayers.Protocol.WFS.v1_0_0"});OpenLayers.Format.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Format.XML,{layerIdentifier:"_layer",featureIdentifier:"_feature",regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},gmlFormat:null,read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));var b=a.documentElement;if(b){var c=this["read_"+b.nodeName];a=c?c.call(this,b):(new OpenLayers.Format.GML(this.options?this.options:{})).read(a)}return a},read_msGMLOutput:function(a){var b=
2977 [];if(a=this.getSiblingNodesByTagCriteria(a,this.layerIdentifier))for(var c=0,d=a.length;c<d;++c){var e=a[c],f=e.nodeName;e.prefix&&(f=f.split(":")[1]);f=f.replace(this.layerIdentifier,"");if(e=this.getSiblingNodesByTagCriteria(e,this.featureIdentifier))for(var g=0;g<e.length;g++){var h=e[g],k=this.parseGeometry(h),h=this.parseAttributes(h),h=new OpenLayers.Feature.Vector(k.geometry,h,null);h.bounds=k.bounds;h.type=f;b.push(h)}}return b},read_FeatureInfoResponse:function(a){var b=[];a=this.getElementsByTagNameNS(a,
2978 "*","FIELDS");for(var c=0,d=a.length;c<d;c++){var e=a[c],f={},g,h=e.attributes.length;if(0<h)for(g=0;g<h;g++){var k=e.attributes[g];f[k.nodeName]=k.nodeValue}else for(e=e.childNodes,g=0,h=e.length;g<h;++g)k=e[g],3!=k.nodeType&&(f[k.getAttribute("name")]=k.getAttribute("value"));b.push(new OpenLayers.Feature.Vector(null,f,null))}return b},getSiblingNodesByTagCriteria:function(a,b){var c=[],d,e,f,g;if(a&&a.hasChildNodes()){d=a.childNodes;f=d.length;for(var h=0;h<f;h++){for(g=d[h];g&&1!=g.nodeType;)g=
2979 g.nextSibling,h++;e=g?g.nodeName:"";0<e.length&&-1<e.indexOf(b)?c.push(g):(e=this.getSiblingNodesByTagCriteria(g,b),0<e.length&&(0==c.length?c=e:c.push(e)))}}return c},parseAttributes:function(a){var b={};if(1==a.nodeType){a=a.childNodes;for(var c=a.length,d=0;d<c;++d){var e=a[d];if(1==e.nodeType){var f=e.childNodes,e=e.prefix?e.nodeName.split(":")[1]:e.nodeName;0==f.length?b[e]=null:1==f.length&&(f=f[0],3==f.nodeType||4==f.nodeType)&&(f=f.nodeValue.replace(this.regExes.trimSpace,""),b[e]=f)}}}return b},
2980 parseGeometry:function(a){this.gmlFormat||(this.gmlFormat=new OpenLayers.Format.GML);a=this.gmlFormat.parseFeature(a);var b,c=null;a&&(b=a.geometry&&a.geometry.clone(),c=a.bounds&&a.bounds.clone(),a.destroy());return{geometry:b,bounds:c}},CLASS_NAME:"OpenLayers.Format.WMSGetFeatureInfo"});OpenLayers.Control.WMTSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:!1,requestEncoding:"KVP",drillDown:!1,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:!0,infoFormat:"text/html",vendorParams:{},format:null,formatOptions:null,handler:null,hoverRequest:null,pending:0,initialize:function(a){a=a||{};a.handlerOptions=a.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[a]);this.format||(this.format=new OpenLayers.Format.WMSGetFeatureInfo(a.formatOptions));
2981 !0===this.drillDown&&(this.hover=!1);this.hover?this.handler=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{delay:250})):(a={},a[this.clickCallback]=this.getInfoForClick,this.handler=new OpenLayers.Handler.Click(this,a,this.handlerOptions.click||{}))},getInfoForClick:function(a){this.request(a.xy,{})},getInfoForHover:function(a){this.request(a.xy,{hover:!0})},cancelHover:function(){this.hoverRequest&&(--this.pending,
2982 0>=this.pending&&(OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait"),this.pending=0),this.hoverRequest.abort(),this.hoverRequest=null)},findLayers:function(){for(var a=this.layers||this.map.layers,b=[],c,d=a.length-1;0<=d&&(c=a[d],!(c instanceof OpenLayers.Layer.WMTS)||(c.requestEncoding!==this.requestEncoding||this.queryVisible&&!c.getVisibility())||(b.push(c),this.drillDown&&!this.hover));--d);return b},buildRequestOptions:function(a,b){var c=this.map.getLonLatFromPixel(b),d=a.getURL(new OpenLayers.Bounds(c.lon,
2983 c.lat,c.lon,c.lat)),d=OpenLayers.Util.getParameters(d),c=a.getTileInfo(c);OpenLayers.Util.extend(d,{service:"WMTS",version:a.version,request:"GetFeatureInfo",infoFormat:this.infoFormat,i:c.i,j:c.j});OpenLayers.Util.applyDefaults(d,this.vendorParams);return{url:OpenLayers.Util.isArray(a.url)?a.url[0]:a.url,params:OpenLayers.Util.upperCaseObject(d),callback:function(c){this.handleResponse(b,c,a)},scope:this}},request:function(a,b){b=b||{};var c=this.findLayers();if(0<c.length){for(var d,e,f=0,g=c.length;f<
2984 g;f++)e=c[f],d=this.events.triggerEvent("beforegetfeatureinfo",{xy:a,layer:e}),!1!==d&&(++this.pending,d=this.buildRequestOptions(e,a),d=OpenLayers.Request.GET(d),!0===b.hover&&(this.hoverRequest=d));0<this.pending&&OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait")}},handleResponse:function(a,b,c){--this.pending;0>=this.pending&&(OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait"),this.pending=0);if(b.status&&(200>b.status||300<=b.status))this.events.triggerEvent("exception",
2985 {xy:a,request:b,layer:c});else{var d=b.responseXML;d&&d.documentElement||(d=b.responseText);var e,f;try{e=this.format.read(d)}catch(g){f=!0,this.events.triggerEvent("exception",{xy:a,request:b,error:g,layer:c})}f||this.events.triggerEvent("getfeatureinfo",{text:b.responseText,features:e,request:b,xy:a,layer:c})}},CLASS_NAME:"OpenLayers.Control.WMTSGetFeatureInfo"});OpenLayers.Protocol.CSW.v2_0_2=OpenLayers.Class(OpenLayers.Protocol,{formatOptions:null,initialize:function(a){OpenLayers.Protocol.prototype.initialize.apply(this,[a]);a.format||(this.format=new OpenLayers.Format.CSWGetRecords.v2_0_2(OpenLayers.Util.extend({},this.formatOptions)))},destroy:function(){this.options&&!this.options.format&&this.format.destroy();this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this)},read:function(a){a=OpenLayers.Util.extend({},a);OpenLayers.Util.applyDefaults(a,
2986 this.options||{});var b=new OpenLayers.Protocol.Response({requestType:"read"}),c=this.format.write(a.params||a);b.priv=OpenLayers.Request.POST({url:a.url,callback:this.createCallback(this.handleRead,b,a),params:a.params,headers:a.headers,data:c});return b},handleRead:function(a,b){if(b.callback){var c=a.priv;200<=c.status&&300>c.status?(a.data=this.parseData(c),a.code=OpenLayers.Protocol.Response.SUCCESS):a.code=OpenLayers.Protocol.Response.FAILURE;b.callback.call(b.scope,a)}},parseData:function(a){var b=
2987 a.responseXML;b&&b.documentElement||(b=a.responseText);return!b||0>=b.length?null:this.format.read(b)},CLASS_NAME:"OpenLayers.Protocol.CSW.v2_0_2"});OpenLayers.Format.WCSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WCSCapabilities.v1,{namespaces:{wcs:"http://www.opengis.net/wcs/1.1",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",ows:"http://www.opengis.net/ows/1.1"},errorProperty:"operationsMetadata",readers:{wcs:OpenLayers.Util.applyDefaults({Capabilities:function(a,b){this.readChildNodes(a,b)},Contents:function(a,b){b.contentMetadata=[];this.readChildNodes(a,b.contentMetadata)},CoverageSummary:function(a,
2988 b){var c={};this.readChildNodes(a,c);b.push(c)},Identifier:function(a,b){b.identifier=this.getChildValue(a)},Title:function(a,b){b.title=this.getChildValue(a)},Abstract:function(a,b){b["abstract"]=this.getChildValue(a)},SupportedCRS:function(a,b){var c=this.getChildValue(a);c&&(b.supportedCRS||(b.supportedCRS=[]),b.supportedCRS.push(c))},SupportedFormat:function(a,b){var c=this.getChildValue(a);c&&(b.supportedFormat||(b.supportedFormat=[]),b.supportedFormat.push(c))}},OpenLayers.Format.WCSCapabilities.v1.prototype.readers.wcs),
2989 ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WCSCapabilities.v1_1_0"});OpenLayers.Control.Graticule=OpenLayers.Class(OpenLayers.Control,{autoActivate:!0,intervals:[45,30,20,10,5,2,1,0.5,0.2,0.1,0.05,0.01,0.005,0.002,0.001],displayInLayerSwitcher:!0,visible:!0,numPoints:50,targetSize:200,layerName:null,labelled:!0,labelFormat:"dm",lineSymbolizer:{strokeColor:"#333",strokeWidth:1,strokeOpacity:0.5},labelSymbolizer:{},gratLayer:null,initialize:function(a){a=a||{};a.layerName=a.layerName||OpenLayers.i18n("Graticule");OpenLayers.Control.prototype.initialize.apply(this,[a]);
2990 this.labelSymbolizer.stroke=!1;this.labelSymbolizer.fill=!1;this.labelSymbolizer.label="${label}";this.labelSymbolizer.labelAlign="${labelAlign}";this.labelSymbolizer.labelXOffset="${xOffset}";this.labelSymbolizer.labelYOffset="${yOffset}"},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);this.gratLayer&&(this.gratLayer.destroy(),this.gratLayer=null)},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.gratLayer){var a=new OpenLayers.Style({},
2991 {rules:[new OpenLayers.Rule({symbolizer:{Point:this.labelSymbolizer,Line:this.lineSymbolizer}})]});this.gratLayer=new OpenLayers.Layer.Vector(this.layerName,{styleMap:new OpenLayers.StyleMap({"default":a}),visibility:this.visible,displayInLayerSwitcher:this.displayInLayerSwitcher})}return this.div},activate:function(){return OpenLayers.Control.prototype.activate.apply(this,arguments)?(this.map.addLayer(this.gratLayer),this.map.events.register("moveend",this,this.update),this.update(),!0):!1},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,
2992 arguments)?(this.map.events.unregister("moveend",this,this.update),this.map.removeLayer(this.gratLayer),!0):!1},update:function(){var a=this.map.getExtent();if(a){this.gratLayer.destroyFeatures();var b=new OpenLayers.Projection("EPSG:4326"),c=this.map.getProjectionObject(),d=this.map.getResolution();c.proj&&"longlat"==c.proj.projName&&(this.numPoints=1);var e=this.map.getCenter(),f=new OpenLayers.Pixel(e.lon,e.lat);OpenLayers.Projection.transform(f,c,b);for(var e=this.targetSize*d,e=e*e,g,d=0;d<this.intervals.length;++d){g=
2993 this.intervals[d];var h=g/2,k=f.offset({x:-h,y:-h}),h=f.offset({x:h,y:h});OpenLayers.Projection.transform(k,b,c);OpenLayers.Projection.transform(h,b,c);if((k.x-h.x)*(k.x-h.x)+(k.y-h.y)*(k.y-h.y)<=e)break}f.x=Math.floor(f.x/g)*g;f.y=Math.floor(f.y/g)*g;var d=0,e=[f.clone()],h=f.clone(),l;do h=h.offset({x:0,y:g}),l=OpenLayers.Projection.transform(h.clone(),b,c),e.unshift(h);while(a.containsPixel(l)&&1E3>++d);h=f.clone();do h=h.offset({x:0,y:-g}),l=OpenLayers.Projection.transform(h.clone(),b,c),e.push(h);
2994 while(a.containsPixel(l)&&1E3>++d);d=0;k=[f.clone()];h=f.clone();do h=h.offset({x:-g,y:0}),l=OpenLayers.Projection.transform(h.clone(),b,c),k.unshift(h);while(a.containsPixel(l)&&1E3>++d);h=f.clone();do h=h.offset({x:g,y:0}),l=OpenLayers.Projection.transform(h.clone(),b,c),k.push(h);while(a.containsPixel(l)&&1E3>++d);g=[];for(d=0;d<k.length;++d){l=k[d].x;for(var f=[],m=null,n=Math.min(e[0].y,90),h=Math.max(e[e.length-1].y,-90),p=(n-h)/this.numPoints,n=h,h=0;h<=this.numPoints;++h){var q=new OpenLayers.Geometry.Point(l,
2995 n);q.transform(b,c);f.push(q);n+=p;q.y>=a.bottom&&!m&&(m=q)}this.labelled&&(m=new OpenLayers.Geometry.Point(m.x,a.bottom),l={value:l,label:this.labelled?OpenLayers.Util.getFormattedLonLat(l,"lon",this.labelFormat):"",labelAlign:"cb",xOffset:0,yOffset:2},this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(m,l)));f=new OpenLayers.Geometry.LineString(f);g.push(new OpenLayers.Feature.Vector(f))}for(h=0;h<e.length;++h)if(n=e[h].y,!(-90>n||90<n)){f=[];d=k[0].x;p=(k[k.length-1].x-d)/this.numPoints;
2996 l=d;m=null;for(d=0;d<=this.numPoints;++d)q=new OpenLayers.Geometry.Point(l,n),q.transform(b,c),f.push(q),l+=p,q.x<a.right&&(m=q);this.labelled&&(m=new OpenLayers.Geometry.Point(a.right,m.y),l={value:n,label:this.labelled?OpenLayers.Util.getFormattedLonLat(n,"lat",this.labelFormat):"",labelAlign:"rb",xOffset:-2,yOffset:2},this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(m,l)));f=new OpenLayers.Geometry.LineString(f);g.push(new OpenLayers.Feature.Vector(f))}this.gratLayer.addFeatures(g)}},CLASS_NAME:"OpenLayers.Control.Graticule"});OpenLayers.Console.warn("OpenLayers.Rico is deprecated");OpenLayers.Rico=OpenLayers.Rico||{};
2997 OpenLayers.Rico.Corner={round:function(a,b){a=OpenLayers.Util.getElement(a);this._setOptions(b);var c=this.options.color;"fromElement"==this.options.color&&(c=this._background(a));var d=this.options.bgColor;"fromParent"==this.options.bgColor&&(d=this._background(a.offsetParent));this._roundCornersImpl(a,c,d)},changeColor:function(a,b){a.style.backgroundColor=b;for(var c=a.parentNode.getElementsByTagName("span"),d=0;d<c.length;d++)c[d].style.backgroundColor=b},changeOpacity:function(a,b){var c="alpha(opacity="+
2998 100*b+")";a.style.opacity=b;a.style.filter=c;for(var d=a.parentNode.getElementsByTagName("span"),e=0;e<d.length;e++)d[e].style.opacity=b,d[e].style.filter=c},reRound:function(a,b){var c=a.parentNode.childNodes[2];a.parentNode.removeChild(a.parentNode.childNodes[0]);a.parentNode.removeChild(c);this.round(a.parentNode,b)},_roundCornersImpl:function(a,b,c){this.options.border&&this._renderBorder(a,c);this._isTopRounded()&&this._roundTopCorners(a,b,c);this._isBottomRounded()&&this._roundBottomCorners(a,
2999 b,c)},_renderBorder:function(a,b){var c="1px solid "+this._borderColor(b);a.innerHTML="<div "+("style='border-left: "+c+";"+("border-right: "+c)+"'")+">"+a.innerHTML+"</div>"},_roundTopCorners:function(a,b,c){for(var d=this._createCorner(c),e=0;e<this.options.numSlices;e++)d.appendChild(this._createCornerSlice(b,c,e,"top"));a.style.paddingTop=0;a.insertBefore(d,a.firstChild)},_roundBottomCorners:function(a,b,c){for(var d=this._createCorner(c),e=this.options.numSlices-1;0<=e;e--)d.appendChild(this._createCornerSlice(b,
3000 c,e,"bottom"));a.style.paddingBottom=0;a.appendChild(d)},_createCorner:function(a){var b=document.createElement("div");b.style.backgroundColor=this._isTransparent()?"transparent":a;return b},_createCornerSlice:function(a,b,c,d){var e=document.createElement("span"),f=e.style;f.backgroundColor=a;f.display="block";f.height="1px";f.overflow="hidden";f.fontSize="1px";a=this._borderColor(a,b);this.options.border&&0==c?(f.borderTopStyle="solid",f.borderTopWidth="1px",f.borderLeftWidth="0px",f.borderRightWidth=
3001 "0px",f.borderBottomWidth="0px",f.height="0px",f.borderColor=a):a&&(f.borderColor=a,f.borderStyle="solid",f.borderWidth="0px 1px");this.options.compact||c!=this.options.numSlices-1||(f.height="2px");this._setMargin(e,c,d);this._setBorder(e,c,d);return e},_setOptions:function(a){this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:!0,border:!1,compact:!1};OpenLayers.Util.extend(this.options,a||{});this.options.numSlices=this.options.compact?2:4;this._isTransparent()&&(this.options.blend=
3002 !1)},_whichSideTop:function(){return this._hasString(this.options.corners,"all","top")||0<=this.options.corners.indexOf("tl")&&0<=this.options.corners.indexOf("tr")?"":0<=this.options.corners.indexOf("tl")?"left":0<=this.options.corners.indexOf("tr")?"right":""},_whichSideBottom:function(){return this._hasString(this.options.corners,"all","bottom")||0<=this.options.corners.indexOf("bl")&&0<=this.options.corners.indexOf("br")?"":0<=this.options.corners.indexOf("bl")?"left":0<=this.options.corners.indexOf("br")?
3003 "right":""},_borderColor:function(a,b){return"transparent"==a?b:this.options.border?this.options.border:this.options.blend?this._blend(b,a):""},_setMargin:function(a,b,c){b=this._marginSize(b);c="top"==c?this._whichSideTop():this._whichSideBottom();"left"==c?(a.style.marginLeft=b+"px",a.style.marginRight="0px"):"right"==c?(a.style.marginRight=b+"px",a.style.marginLeft="0px"):(a.style.marginLeft=b+"px",a.style.marginRight=b+"px")},_setBorder:function(a,b,c){b=this._borderSize(b);c="top"==c?this._whichSideTop():
3004 this._whichSideBottom();"left"==c?(a.style.borderLeftWidth=b+"px",a.style.borderRightWidth="0px"):"right"==c?(a.style.borderRightWidth=b+"px",a.style.borderLeftWidth="0px"):(a.style.borderLeftWidth=b+"px",a.style.borderRightWidth=b+"px");!1!=this.options.border&&(a.style.borderLeftWidth=b+"px",a.style.borderRightWidth=b+"px")},_marginSize:function(a){if(this._isTransparent())return 0;var b=[5,3,2,1],c=[3,2,1,0],d=[2,1],e=[1,0];return this.options.compact&&this.options.blend?e[a]:this.options.compact?
3005 d[a]:this.options.blend?c[a]:b[a]},_borderSize:function(a){var b=[5,3,2,1],c=[2,1,1,1],d=[1,0],e=[0,2,0,0];return this.options.compact&&(this.options.blend||this._isTransparent())?1:this.options.compact?d[a]:this.options.blend?c[a]:this.options.border?e[a]:this._isTransparent()?b[a]:0},_hasString:function(a){for(var b=1;b<arguments.length;b++)if(0<=a.indexOf(arguments[b]))return!0;return!1},_blend:function(a,b){var c=OpenLayers.Rico.Color.createFromHex(a);c.blend(OpenLayers.Rico.Color.createFromHex(b));
3006 return c},_background:function(a){try{return OpenLayers.Rico.Color.createColorFromBackground(a).asHex()}catch(b){return"#ffffff"}},_isTransparent:function(){return"transparent"==this.options.color},_isTopRounded:function(){return this._hasString(this.options.corners,"all","top","tl","tr")},_isBottomRounded:function(){return this._hasString(this.options.corners,"all","bottom","bl","br")},_hasSingleTextChild:function(a){return 1==a.childNodes.length&&3==a.childNodes[0].nodeType}};OpenLayers.Control.NavigationHistory=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOGGLE,previous:null,previousOptions:null,next:null,nextOptions:null,limit:50,autoActivate:!0,clearOnDeactivate:!1,registry:null,nextStack:null,previousStack:null,listeners:null,restoring:!1,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,[a]);this.registry=OpenLayers.Util.extend({moveend:this.getState},this.registry);a={trigger:OpenLayers.Function.bind(this.previousTrigger,
3007 this),displayClass:this.displayClass+" "+this.displayClass+"Previous"};OpenLayers.Util.extend(a,this.previousOptions);this.previous=new OpenLayers.Control.Button(a);a={trigger:OpenLayers.Function.bind(this.nextTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Next"};OpenLayers.Util.extend(a,this.nextOptions);this.next=new OpenLayers.Control.Button(a);this.clear()},onPreviousChange:function(a,b){a&&!this.previous.active?this.previous.activate():!a&&this.previous.active&&this.previous.deactivate()},
3008 onNextChange:function(a,b){a&&!this.next.active?this.next.activate():!a&&this.next.active&&this.next.deactivate()},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this);this.previous.destroy();this.next.destroy();this.deactivate();for(var a in this)this[a]=null},setMap:function(a){this.map=a;this.next.setMap(a);this.previous.setMap(a)},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.next.draw();this.previous.draw()},previousTrigger:function(){var a=this.previousStack.shift(),
3009 b=this.previousStack.shift();void 0!=b?(this.nextStack.unshift(a),this.previousStack.unshift(b),this.restoring=!0,this.restore(b),this.restoring=!1,this.onNextChange(this.nextStack[0],this.nextStack.length),this.onPreviousChange(this.previousStack[1],this.previousStack.length-1)):this.previousStack.unshift(a);return b},nextTrigger:function(){var a=this.nextStack.shift();void 0!=a&&(this.previousStack.unshift(a),this.restoring=!0,this.restore(a),this.restoring=!1,this.onNextChange(this.nextStack[0],
3010 this.nextStack.length),this.onPreviousChange(this.previousStack[1],this.previousStack.length-1));return a},clear:function(){this.previousStack=[];this.previous.deactivate();this.nextStack=[];this.next.deactivate()},getState:function(){return{center:this.map.getCenter(),resolution:this.map.getResolution(),projection:this.map.getProjectionObject(),units:this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units}},restore:function(a){var b,c;if(this.map.getProjectionObject()==
3011 a.projection)c=this.map.getZoomForResolution(a.resolution),b=a.center;else{b=a.center.clone();b.transform(a.projection,this.map.getProjectionObject());c=a.units;var d=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;c=this.map.getZoomForResolution((c&&d?OpenLayers.INCHES_PER_UNIT[c]/OpenLayers.INCHES_PER_UNIT[d]:1)*a.resolution)}this.map.setCenter(b,c)},setListeners:function(){this.listeners={};for(var a in this.registry)this.listeners[a]=OpenLayers.Function.bind(function(){if(!this.restoring){var b=
3012 this.registry[a].apply(this,arguments);this.previousStack.unshift(b);if(1<this.previousStack.length)this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);this.previousStack.length>this.limit+1&&this.previousStack.pop();0<this.nextStack.length&&(this.nextStack=[],this.onNextChange(null,0))}return!0},this)},activate:function(){var a=!1;if(this.map&&OpenLayers.Control.prototype.activate.apply(this)){null==this.listeners&&this.setListeners();for(var b in this.listeners)this.map.events.register(b,
3013 this,this.listeners[b]);a=!0;0==this.previousStack.length&&this.initStack()}return a},initStack:function(){this.map.getCenter()&&this.listeners.moveend()},deactivate:function(){var a=!1;if(this.map&&OpenLayers.Control.prototype.deactivate.apply(this)){for(var b in this.listeners)this.map.events.unregister(b,this,this.listeners[b]);this.clearOnDeactivate&&this.clear();a=!0}return a},CLASS_NAME:"OpenLayers.Control.NavigationHistory"});OpenLayers.Layer.UTFGrid=OpenLayers.Class(OpenLayers.Layer.XYZ,{isBaseLayer:!1,projection:new OpenLayers.Projection("EPSG:900913"),useJSONP:!1,tileClass:OpenLayers.Tile.UTFGrid,initialize:function(a){OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a.name,a.url,{},a]);this.tileOptions=OpenLayers.Util.extend({utfgridResolution:this.utfgridResolution},this.tileOptions)},createBackBuffer:function(){},clone:function(a){null==a&&(a=new OpenLayers.Layer.UTFGrid(this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,
3014 [a])},getFeatureInfo:function(a){var b=null;(a=this.getTileData(a))&&a.tile&&(b=a.tile.getFeatureInfo(a.i,a.j));return b},getFeatureId:function(a){var b=null;a=this.getTileData(a);a.tile&&(b=a.tile.getFeatureId(a.i,a.j));return b},CLASS_NAME:"OpenLayers.Layer.UTFGrid"});OpenLayers.TileManager=OpenLayers.Class({cacheSize:256,tilesPerFrame:2,frameDelay:16,moveDelay:100,zoomDelay:200,maps:null,tileQueueId:null,tileQueue:null,tileCache:null,tileCacheIndex:null,initialize:function(a){OpenLayers.Util.extend(this,a);this.maps=[];this.tileQueueId={};this.tileQueue={};this.tileCache={};this.tileCacheIndex=[]},addMap:function(a){if(!this._destroyed&&OpenLayers.Layer.Grid){this.maps.push(a);this.tileQueue[a.id]=[];for(var b=0,c=a.layers.length;b<c;++b)this.addLayer({layer:a.layers[b]});
3015 a.events.on({move:this.move,zoomend:this.zoomEnd,changelayer:this.changeLayer,addlayer:this.addLayer,preremovelayer:this.removeLayer,scope:this})}},removeMap:function(a){if(!this._destroyed&&OpenLayers.Layer.Grid){window.clearTimeout(this.tileQueueId[a.id]);if(a.layers)for(var b=0,c=a.layers.length;b<c;++b)this.removeLayer({layer:a.layers[b]});a.events&&a.events.un({move:this.move,zoomend:this.zoomEnd,changelayer:this.changeLayer,addlayer:this.addLayer,preremovelayer:this.removeLayer,scope:this});
3016 delete this.tileQueue[a.id];delete this.tileQueueId[a.id];OpenLayers.Util.removeItem(this.maps,a)}},move:function(a){this.updateTimeout(a.object,this.moveDelay,!0)},zoomEnd:function(a){this.updateTimeout(a.object,this.zoomDelay)},changeLayer:function(a){"visibility"!==a.property&&"params"!==a.property||this.updateTimeout(a.object,0)},addLayer:function(a){a=a.layer;if(a instanceof OpenLayers.Layer.Grid){a.events.on({addtile:this.addTile,retile:this.clearTileQueue,scope:this});var b,c,d;for(b=a.grid.length-
3017 1;0<=b;--b)for(c=a.grid[b].length-1;0<=c;--c)d=a.grid[b][c],this.addTile({tile:d}),d.url&&!d.imgDiv&&this.manageTileCache({object:d})}},removeLayer:function(a){a=a.layer;if(a instanceof OpenLayers.Layer.Grid&&(this.clearTileQueue({object:a}),a.events&&a.events.un({addtile:this.addTile,retile:this.clearTileQueue,scope:this}),a.grid)){var b,c,d;for(b=a.grid.length-1;0<=b;--b)for(c=a.grid[b].length-1;0<=c;--c)d=a.grid[b][c],this.unloadTile({object:d})}},updateTimeout:function(a,b,c){window.clearTimeout(this.tileQueueId[a.id]);
3018 var d=this.tileQueue[a.id];if(!c||d.length)this.tileQueueId[a.id]=window.setTimeout(OpenLayers.Function.bind(function(){this.drawTilesFromQueue(a);d.length&&this.updateTimeout(a,this.frameDelay)},this),b)},addTile:function(a){if(a.tile instanceof OpenLayers.Tile.Image)a.tile.events.on({beforedraw:this.queueTileDraw,beforeload:this.manageTileCache,loadend:this.addToCache,unload:this.unloadTile,scope:this});else this.removeLayer({layer:a.tile.layer})},unloadTile:function(a){a=a.object;a.events.un({beforedraw:this.queueTileDraw,
3019 beforeload:this.manageTileCache,loadend:this.addToCache,unload:this.unloadTile,scope:this});OpenLayers.Util.removeItem(this.tileQueue[a.layer.map.id],a)},queueTileDraw:function(a){a=a.object;var b=!1,c=a.layer,d=c.getURL(a.bounds),e=this.tileCache[d];e&&"olTileImage"!==e.className&&(delete this.tileCache[d],OpenLayers.Util.removeItem(this.tileCacheIndex,d),e=null);!c.url||!c.async&&e||(b=this.tileQueue[c.map.id],~OpenLayers.Util.indexOf(b,a)||b.push(a),b=!0);return!b},drawTilesFromQueue:function(a){var b=
3020 this.tileQueue[a.id],c=this.tilesPerFrame;for(a=a.zoomTween&&a.zoomTween.playing;!a&&b.length&&c;)b.shift().draw(!0),--c},manageTileCache:function(a){a=a.object;var b=this.tileCache[a.url];b&&(b.parentNode&&OpenLayers.Element.hasClass(b.parentNode,"olBackBuffer")&&(b.parentNode.removeChild(b),b.id=null),b.parentNode||(b.style.visibility="hidden",b.style.opacity=0,a.setImage(b),OpenLayers.Util.removeItem(this.tileCacheIndex,a.url),this.tileCacheIndex.push(a.url)))},addToCache:function(a){a=a.object;
3021 this.tileCache[a.url]||OpenLayers.Element.hasClass(a.imgDiv,"olImageLoadError")||(this.tileCacheIndex.length>=this.cacheSize&&(delete this.tileCache[this.tileCacheIndex[0]],this.tileCacheIndex.shift()),this.tileCache[a.url]=a.imgDiv,this.tileCacheIndex.push(a.url))},clearTileQueue:function(a){a=a.object;for(var b=this.tileQueue[a.map.id],c=b.length-1;0<=c;--c)b[c].layer===a&&b.splice(c,1)},destroy:function(){for(var a=this.maps.length-1;0<=a;--a)this.removeMap(this.maps[a]);this.tileCacheIndex=this.tileCache=
3022 this.tileQueueId=this.tileQueue=this.maps=null;this._destroyed=!0}});OpenLayers.Layer.ArcGISCache=OpenLayers.Class(OpenLayers.Layer.XYZ,{url:null,tileOrigin:null,tileSize:new OpenLayers.Size(256,256),useArcGISServer:!0,type:"png",useScales:!1,overrideDPI:!1,initialize:function(a,b,c){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);this.resolutions&&(this.serverResolutions=this.resolutions,this.maxExtent=this.getMaxExtentForResolution(this.resolutions[0]));if(this.layerInfo){var d=this.layerInfo,e=new OpenLayers.Bounds(d.fullExtent.xmin,d.fullExtent.ymin,
3023 d.fullExtent.xmax,d.fullExtent.ymax);this.projection="EPSG:"+d.spatialReference.wkid;this.sphericalMercator=102100==d.spatialReference.wkid;this.units="esriFeet"==d.units?"ft":"m";if(d.tileInfo){this.tileSize=new OpenLayers.Size(d.tileInfo.width||d.tileInfo.cols,d.tileInfo.height||d.tileInfo.rows);this.tileOrigin=new OpenLayers.LonLat(d.tileInfo.origin.x,d.tileInfo.origin.y);var f=new OpenLayers.Geometry.Point(e.left,e.top),e=new OpenLayers.Geometry.Point(e.right,e.bottom);this.useScales?this.scales=
3024 []:this.resolutions=[];this.lods=[];for(var g in d.tileInfo.lods)if(d.tileInfo.lods.hasOwnProperty(g)){var h=d.tileInfo.lods[g];this.useScales?this.scales.push(h.scale):this.resolutions.push(h.resolution);var k=this.getContainingTileCoords(f,h.resolution);h.startTileCol=k.x;h.startTileRow=k.y;k=this.getContainingTileCoords(e,h.resolution);h.endTileCol=k.x;h.endTileRow=k.y;this.lods.push(h)}this.maxExtent=this.calculateMaxExtentWithLOD(this.lods[0]);this.serverResolutions=this.resolutions;this.overrideDPI&&
3025 d.tileInfo.dpi&&(OpenLayers.DOTS_PER_INCH=d.tileInfo.dpi)}}},getContainingTileCoords:function(a,b){return new OpenLayers.Pixel(Math.max(Math.floor((a.x-this.tileOrigin.lon)/(this.tileSize.w*b)),0),Math.max(Math.floor((this.tileOrigin.lat-a.y)/(this.tileSize.h*b)),0))},calculateMaxExtentWithLOD:function(a){var b=this.tileOrigin.lon+a.startTileCol*this.tileSize.w*a.resolution,c=this.tileOrigin.lat-a.startTileRow*this.tileSize.h*a.resolution;return new OpenLayers.Bounds(b,c-(a.endTileRow-a.startTileRow+
3026 1)*this.tileSize.h*a.resolution,b+(a.endTileCol-a.startTileCol+1)*this.tileSize.w*a.resolution,c)},calculateMaxExtentWithExtent:function(a,b){var c=new OpenLayers.Geometry.Point(a.left,a.top),d=new OpenLayers.Geometry.Point(a.right,a.bottom),c=this.getContainingTileCoords(c,b),d=this.getContainingTileCoords(d,b);return this.calculateMaxExtentWithLOD({resolution:b,startTileCol:c.x,startTileRow:c.y,endTileCol:d.x,endTileRow:d.y})},getUpperLeftTileCoord:function(a){var b=new OpenLayers.Geometry.Point(this.maxExtent.left,
3027 this.maxExtent.top);return this.getContainingTileCoords(b,a)},getLowerRightTileCoord:function(a){var b=new OpenLayers.Geometry.Point(this.maxExtent.right,this.maxExtent.bottom);return this.getContainingTileCoords(b,a)},getMaxExtentForResolution:function(a){var b=this.getUpperLeftTileCoord(a),c=this.getLowerRightTileCoord(a),d=this.tileOrigin.lon+b.x*this.tileSize.w*a,e=this.tileOrigin.lat-b.y*this.tileSize.h*a;return new OpenLayers.Bounds(d,e-(c.y-b.y+1)*this.tileSize.h*a,d+(c.x-b.x+1)*this.tileSize.w*
3028 a,e)},clone:function(a){null==a&&(a=new OpenLayers.Layer.ArcGISCache(this.name,this.url,this.options));return OpenLayers.Layer.XYZ.prototype.clone.apply(this,[a])},initGriddedTiles:function(a){delete this._tileOrigin;OpenLayers.Layer.XYZ.prototype.initGriddedTiles.apply(this,arguments)},getMaxExtent:function(){var a=this.map.getResolution();return this.maxExtent=this.getMaxExtentForResolution(a)},getTileOrigin:function(){if(!this._tileOrigin){var a=this.getMaxExtent();this._tileOrigin=new OpenLayers.LonLat(a.left,
3029 a.bottom)}return this._tileOrigin},getURL:function(a){var b=this.getResolution(),c=this.tileOrigin.lon+b*this.tileSize.w/2,d=this.tileOrigin.lat-b*this.tileSize.h/2;a=a.getCenterLonLat();c=Math.round(Math.abs((a.lon-c)/(b*this.tileSize.w)));d=Math.round(Math.abs((d-a.lat)/(b*this.tileSize.h)));a=this.map.getZoom();if(this.lods){if(b=this.lods[this.map.getZoom()],c<b.startTileCol||c>b.endTileCol||d<b.startTileRow||d>b.endTileRow)return null}else{var e=this.getUpperLeftTileCoord(b),b=this.getLowerRightTileCoord(b);
3030 if(c<e.x||c>=b.x||d<e.y||d>=b.y)return null}b=this.url;e=""+c+d+a;OpenLayers.Util.isArray(b)&&(b=this.selectUrl(e,b));this.useArcGISServer?b+="/tile/${z}/${y}/${x}":(c="C"+OpenLayers.Number.zeroPad(c,8,16),d="R"+OpenLayers.Number.zeroPad(d,8,16),a="L"+OpenLayers.Number.zeroPad(a,2,10),b=b+"/${z}/${y}/${x}."+this.type);b=OpenLayers.String.format(b,{x:c,y:d,z:a});return OpenLayers.Util.urlAppend(b,OpenLayers.Util.getParameterString(this.params))},CLASS_NAME:"OpenLayers.Layer.ArcGISCache"});OpenLayers.Control.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:!1,drillDown:!1,maxFeatures:10,clickCallback:"click",output:"features",layers:null,queryVisible:!1,url:null,layerUrls:null,infoFormat:"text/html",vendorParams:{},format:null,formatOptions:null,handler:null,hoverRequest:null,initialize:function(a){a=a||{};a.handlerOptions=a.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[a]);this.format||(this.format=new OpenLayers.Format.WMSGetFeatureInfo(a.formatOptions));
3031 !0===this.drillDown&&(this.hover=!1);this.hover?this.handler=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{delay:250})):(a={},a[this.clickCallback]=this.getInfoForClick,this.handler=new OpenLayers.Handler.Click(this,a,this.handlerOptions.click||{}))},getInfoForClick:function(a){this.events.triggerEvent("beforegetfeatureinfo",{xy:a.xy});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");this.request(a.xy,
3032 {})},getInfoForHover:function(a){this.events.triggerEvent("beforegetfeatureinfo",{xy:a.xy});this.request(a.xy,{hover:!0})},cancelHover:function(){this.hoverRequest&&(this.hoverRequest.abort(),this.hoverRequest=null)},findLayers:function(){for(var a=this.layers||this.map.layers,b=[],c,d,e=a.length-1;0<=e;--e)c=a[e],c instanceof OpenLayers.Layer.WMS&&(!this.queryVisible||c.getVisibility())&&(d=OpenLayers.Util.isArray(c.url)?c.url[0]:c.url,!1!==this.drillDown||this.url||(this.url=d),(!0===this.drillDown||
3033 this.urlMatches(d))&&b.push(c));return b},urlMatches:function(a){var b=OpenLayers.Util.isEquivalentUrl(this.url,a);if(!b&&this.layerUrls)for(var c=0,d=this.layerUrls.length;c<d;++c)if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[c],a)){b=!0;break}return b},buildWMSOptions:function(a,b,c,d){for(var e=[],f=[],g=0,h=b.length;g<h;g++)null!=b[g].params.LAYERS&&(e=e.concat(b[g].params.LAYERS),f=f.concat(this.getStyleNames(b[g])));b=b[0];g=this.map.getProjection();(h=b.projection)&&h.equals(this.map.getProjectionObject())&&
3034 (g=h.getCode());d=OpenLayers.Util.extend({service:"WMS",version:b.params.VERSION,request:"GetFeatureInfo",exceptions:b.params.EXCEPTIONS,bbox:this.map.getExtent().toBBOX(null,b.reverseAxisOrder()),feature_count:this.maxFeatures,height:this.map.getSize().h,width:this.map.getSize().w,format:d,info_format:b.params.INFO_FORMAT||this.infoFormat},1.3<=parseFloat(b.params.VERSION)?{crs:g,i:parseInt(c.x),j:parseInt(c.y)}:{srs:g,x:parseInt(c.x),y:parseInt(c.y)});0!=e.length&&(d=OpenLayers.Util.extend({layers:e,
3035 query_layers:e,styles:f},d));OpenLayers.Util.applyDefaults(d,this.vendorParams);return{url:a,params:OpenLayers.Util.upperCaseObject(d),callback:function(b){this.handleResponse(c,b,a)},scope:this}},getStyleNames:function(a){return a.params.STYLES?a.params.STYLES:OpenLayers.Util.isArray(a.params.LAYERS)?Array(a.params.LAYERS.length):a.params.LAYERS.replace(/[^,]/g,"")},request:function(a,b){var c=this.findLayers();if(0==c.length)this.events.triggerEvent("nogetfeatureinfo"),OpenLayers.Element.removeClass(this.map.viewPortDiv,
3036 "olCursorWait");else if(b=b||{},!1===this.drillDown){var c=this.buildWMSOptions(this.url,c,a,c[0].params.FORMAT),d=OpenLayers.Request.GET(c);!0===b.hover&&(this.hoverRequest=d)}else{this._numRequests=this._requestCount=0;this.features=[];for(var d={},e,f=0,g=c.length;f<g;f++){var h=c[f];e=OpenLayers.Util.isArray(h.url)?h.url[0]:h.url;e in d?d[e].push(h):(this._numRequests++,d[e]=[h])}for(e in d)c=d[e],c=this.buildWMSOptions(e,c,a,c[0].params.FORMAT),OpenLayers.Request.GET(c)}},triggerGetFeatureInfo:function(a,
3037 b,c){this.events.triggerEvent("getfeatureinfo",{text:a.responseText,features:c,request:a,xy:b});OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait")},handleResponse:function(a,b,c){var d=b.responseXML;d&&d.documentElement||(d=b.responseText);d=this.format.read(d);!1===this.drillDown?this.triggerGetFeatureInfo(b,a,d):(this._requestCount++,this._features="object"===this.output?(this._features||[]).concat({url:c,features:d}):(this._features||[]).concat(d),this._requestCount===this._numRequests&&
3038 (this.triggerGetFeatureInfo(b,a,this._features.concat()),delete this._features,delete this._requestCount,delete this._numRequests))},CLASS_NAME:"OpenLayers.Control.WMSGetFeatureInfo"});OpenLayers.Format.WMSCapabilities.v1_3_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_3,{version:"1.3.0",CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3_0"});OpenLayers.Format.SOSGetFeatureOfInterest=OpenLayers.Class(OpenLayers.Format.XML,{VERSION:"1.0.0",namespaces:{sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",sa:"http://www.opengis.net/sampling/1.0",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",defaultPrefix:"sos",regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},read:function(a){"string"==
3039 typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={features:[]};this.readNode(a,b);a=[];for(var c=0,d=b.features.length;c<d;c++){var e=b.features[c];this.internalProjection&&(this.externalProjection&&e.components[0])&&e.components[0].transform(this.externalProjection,this.internalProjection);e=new OpenLayers.Feature.Vector(e.components[0],e.attributes);a.push(e)}return a},readers:{sa:{SamplingPoint:function(a,b){if(!b.attributes){var c=
3040 {attributes:{}};b.features.push(c);b=c}b.attributes.id=this.getAttributeNS(a,this.namespaces.gml,"id");this.readChildNodes(a,b)},position:function(a,b){this.readChildNodes(a,b)}},gml:OpenLayers.Util.applyDefaults({FeatureCollection:function(a,b){this.readChildNodes(a,b)},featureMember:function(a,b){var c={attributes:{}};b.features.push(c);this.readChildNodes(a,c)},name:function(a,b){b.attributes.name=this.getChildValue(a)},pos:function(a,b){this.externalProjection||(this.externalProjection=new OpenLayers.Projection(a.getAttribute("srsName")));
3041 OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[a,b])}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{sos:{GetFeatureOfInterest:function(a){for(var b=this.createElementNSPlus("GetFeatureOfInterest",{attributes:{version:this.VERSION,service:"SOS","xsi:schemaLocation":this.schemaLocation}}),c=0,d=a.fois.length;c<d;c++)this.writeNode("FeatureOfInterestId",{foi:a.fois[c]},b);return b},FeatureOfInterestId:function(a){return this.createElementNSPlus("FeatureOfInterestId",{value:a.foi})}}},
3042 CLASS_NAME:"OpenLayers.Format.SOSGetFeatureOfInterest"});OpenLayers.Format.SOSGetObservation=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows",gml:"http://www.opengis.net/gml",sos:"http://www.opengis.net/sos/1.0",ogc:"http://www.opengis.net/ogc",om:"http://www.opengis.net/om/1.0",sa:"http://www.opengis.net/sampling/1.0",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",
3043 defaultPrefix:"sos",read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={measurements:[],observations:[]};this.readNode(a,b);return b},write:function(a){a=this.writeNode("sos:GetObservation",a);a.setAttribute("xmlns:om",this.namespaces.om);a.setAttribute("xmlns:ogc",this.namespaces.ogc);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,
3044 [a])},readers:{om:{ObservationCollection:function(a,b){b.id=this.getAttributeNS(a,this.namespaces.gml,"id");this.readChildNodes(a,b)},member:function(a,b){this.readChildNodes(a,b)},Measurement:function(a,b){var c={};b.measurements.push(c);this.readChildNodes(a,c)},Observation:function(a,b){var c={};b.observations.push(c);this.readChildNodes(a,c)},samplingTime:function(a,b){var c={};b.samplingTime=c;this.readChildNodes(a,c)},observedProperty:function(a,b){b.observedProperty=this.getAttributeNS(a,this.namespaces.xlink,
3045 "href");this.readChildNodes(a,b)},procedure:function(a,b){b.procedure=this.getAttributeNS(a,this.namespaces.xlink,"href");this.readChildNodes(a,b)},featureOfInterest:function(a,b){var c={features:[]};b.fois=[];b.fois.push(c);this.readChildNodes(a,c);for(var d=[],e=0,f=c.features.length;e<f;e++){var g=c.features[e];d.push(new OpenLayers.Feature.Vector(g.components[0],g.attributes))}c.features=d},result:function(a,b){var c={};b.result=c;""!==this.getChildValue(a)?(c.value=this.getChildValue(a),c.uom=
3046 a.getAttribute("uom")):this.readChildNodes(a,c)}},sa:OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.sa,gml:OpenLayers.Util.applyDefaults({TimeInstant:function(a,b){var c={};b.timeInstant=c;this.readChildNodes(a,c)},timePosition:function(a,b){b.timePosition=this.getChildValue(a)}},OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.gml)},writers:{sos:{GetObservation:function(a){var b=this.createElementNSPlus("GetObservation",{attributes:{version:this.VERSION,service:"SOS"}});this.writeNode("offering",
3047 a,b);a.eventTime&&this.writeNode("eventTime",a,b);for(var c in a.procedures)this.writeNode("procedure",a.procedures[c],b);for(var d in a.observedProperties)this.writeNode("observedProperty",a.observedProperties[d],b);a.foi&&this.writeNode("featureOfInterest",a.foi,b);this.writeNode("responseFormat",a,b);a.resultModel&&this.writeNode("resultModel",a,b);a.responseMode&&this.writeNode("responseMode",a,b);return b},featureOfInterest:function(a){var b=this.createElementNSPlus("featureOfInterest");this.writeNode("ObjectID",
3048 a.objectId,b);return b},ObjectID:function(a){return this.createElementNSPlus("ObjectID",{value:a})},responseFormat:function(a){return this.createElementNSPlus("responseFormat",{value:a.responseFormat})},procedure:function(a){return this.createElementNSPlus("procedure",{value:a})},offering:function(a){return this.createElementNSPlus("offering",{value:a.offering})},observedProperty:function(a){return this.createElementNSPlus("observedProperty",{value:a})},eventTime:function(a){var b=this.createElementNSPlus("eventTime");
3049 "latest"===a.eventTime&&this.writeNode("ogc:TM_Equals",a,b);return b},resultModel:function(a){return this.createElementNSPlus("resultModel",{value:a.resultModel})},responseMode:function(a){return this.createElementNSPlus("responseMode",{value:a.responseMode})}},ogc:{TM_Equals:function(a){var b=this.createElementNSPlus("ogc:TM_Equals");this.writeNode("ogc:PropertyName",{property:"urn:ogc:data:time:iso8601"},b);"latest"===a.eventTime&&this.writeNode("gml:TimeInstant",{value:"latest"},b);return b},PropertyName:function(a){return this.createElementNSPlus("ogc:PropertyName",
3050 {value:a.property})}},gml:{TimeInstant:function(a){var b=this.createElementNSPlus("gml:TimeInstant");this.writeNode("gml:timePosition",a,b);return b},timePosition:function(a){return this.createElementNSPlus("gml:timePosition",{value:a.value})}}},CLASS_NAME:"OpenLayers.Format.SOSGetObservation"});OpenLayers.Control.UTFGrid=OpenLayers.Class(OpenLayers.Control,{autoActivate:!0,layers:null,defaultHandlerOptions:{delay:300,pixelTolerance:4,stopMove:!1,single:!0,"double":!1,stopSingle:!1,stopDouble:!1},handlerMode:"click",setHandler:function(a){this.handlerMode=a;this.resetHandler()},resetHandler:function(){this.handler&&(this.handler.deactivate(),this.handler.destroy(),this.handler=null);"hover"==this.handlerMode?this.handler=new OpenLayers.Handler.Hover(this,{pause:this.handleEvent,move:this.reset},
3051 this.handlerOptions):"click"==this.handlerMode?this.handler=new OpenLayers.Handler.Click(this,{click:this.handleEvent},this.handlerOptions):"move"==this.handlerMode&&(this.handler=new OpenLayers.Handler.Hover(this,{pause:this.handleEvent,move:this.handleEvent},this.handlerOptions));return this.handler?!0:!1},initialize:function(a){a=a||{};a.handlerOptions=a.handlerOptions||this.defaultHandlerOptions;OpenLayers.Control.prototype.initialize.apply(this,[a]);this.resetHandler()},handleEvent:function(a){if(null==
3052 a)this.reset();else{var b=this.map.getLonLatFromPixel(a.xy);if(b){var c=this.findLayers();if(0<c.length){for(var d={},e,f,g=0,h=c.length;g<h;g++)e=c[g],f=OpenLayers.Util.indexOf(this.map.layers,e),d[f]=e.getFeatureInfo(b);this.callback(d,b,a.xy)}}}},callback:function(a){},reset:function(a){this.callback(null)},findLayers:function(){for(var a=this.layers||this.map.layers,b=[],c,d=a.length-1;0<=d;--d)c=a[d],c instanceof OpenLayers.Layer.UTFGrid&&b.push(c);return b},CLASS_NAME:"OpenLayers.Control.UTFGrid"});OpenLayers.Format.CQL=function(){function a(a){function b(){var a=e.pop();switch(a.type){case "LOGICAL":var c=b(),g=b();return new OpenLayers.Filter.Logical({filters:[g,c],type:f[a.text.toUpperCase()]});case "NOT":return a=b(),new OpenLayers.Filter.Logical({filters:[a],type:OpenLayers.Filter.Logical.NOT});case "BETWEEN":return e.pop(),g=b(),a=b(),c=b(),new OpenLayers.Filter.Comparison({property:c,lowerBoundary:a,upperBoundary:g,type:OpenLayers.Filter.Comparison.BETWEEN});case "COMPARISON":return g=
3053 b(),c=b(),new OpenLayers.Filter.Comparison({property:c,value:g,type:d[a.text.toUpperCase()]});case "IS_NULL":return c=b(),new OpenLayers.Filter.Comparison({property:c,type:d[a.text.toUpperCase()]});case "VALUE":return(c=a.text.match(/^'(.*)'$/))?c[1].replace(/''/g,"'"):Number(a.text);case "SPATIAL":switch(a.text.toUpperCase()){case "BBOX":var a=b(),c=b(),g=b(),h=b(),k=b();return new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:k,value:OpenLayers.Bounds.fromArray([h,g,c,
3054 a])});case "INTERSECTS":return g=b(),c=b(),new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:c,value:g});case "WITHIN":return g=b(),c=b(),new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.WITHIN,property:c,value:g});case "CONTAINS":return g=b(),c=b(),new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.CONTAINS,property:c,value:g});case "DWITHIN":return a=b(),g=b(),c=b(),new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,value:g,
3055 property:c,distance:Number(a)})}case "GEOMETRY":return OpenLayers.Geometry.fromWKT(a.text);default:return a.text}}for(var c=[],e=[];a.length;){var g=a.shift();switch(g.type){case "PROPERTY":case "GEOMETRY":case "VALUE":e.push(g);break;case "COMPARISON":case "BETWEEN":case "IS_NULL":case "LOGICAL":for(var k=h[g.type];0<c.length&&h[c[c.length-1].type]<=k;)e.push(c.pop());c.push(g);break;case "SPATIAL":case "NOT":case "LPAREN":c.push(g);break;case "RPAREN":for(;0<c.length&&"LPAREN"!=c[c.length-1].type;)e.push(c.pop());
3056 c.pop();0<c.length&&"SPATIAL"==c[c.length-1].type&&e.push(c.pop());case "COMMA":case "END":break;default:throw Error("Unknown token type "+g.type);}}for(;0<c.length;)e.push(c.pop());a=b();if(0<e.length){a="Remaining tokens after building AST: \n";for(c=e.length-1;0<=c;c--)a+=e[c].type+": "+e[c].text+"\n";throw Error(a);}return a}var b={PROPERTY:/^[_a-zA-Z]\w*/,COMPARISON:/^(=|<>|<=|<|>=|>|LIKE)/i,IS_NULL:/^IS NULL/i,COMMA:/^,/,LOGICAL:/^(AND|OR)/i,VALUE:/^('([^']|'')*'|\d+(\.\d*)?|\.\d+)/,LPAREN:/^\(/,
3057 RPAREN:/^\)/,SPATIAL:/^(BBOX|INTERSECTS|DWITHIN|WITHIN|CONTAINS)/i,NOT:/^NOT/i,BETWEEN:/^BETWEEN/i,GEOMETRY:function(a){var b=/^(POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)/.exec(a);if(b){var c=a.length,b=a.indexOf("(",b[0].length);if(-1<b)for(var d=1;b<c&&0<d;)switch(b++,a.charAt(b)){case "(":d++;break;case ")":d--}return[a.substr(0,b+1)]}},END:/^$/},c={LPAREN:["GEOMETRY","SPATIAL","PROPERTY","VALUE","LPAREN"],RPAREN:["NOT","LOGICAL","END","RPAREN"],PROPERTY:["COMPARISON",
3058 "BETWEEN","COMMA","IS_NULL"],BETWEEN:["VALUE"],IS_NULL:["END"],COMPARISON:["VALUE"],COMMA:["GEOMETRY","VALUE","PROPERTY"],VALUE:["LOGICAL","COMMA","RPAREN","END"],SPATIAL:["LPAREN"],LOGICAL:["NOT","VALUE","SPATIAL","PROPERTY","LPAREN"],NOT:["PROPERTY","LPAREN"],GEOMETRY:["COMMA","RPAREN"]},d={"=":OpenLayers.Filter.Comparison.EQUAL_TO,"<>":OpenLayers.Filter.Comparison.NOT_EQUAL_TO,"<":OpenLayers.Filter.Comparison.LESS_THAN,"<=":OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,">":OpenLayers.Filter.Comparison.GREATER_THAN,
3059 ">=":OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,LIKE:OpenLayers.Filter.Comparison.LIKE,BETWEEN:OpenLayers.Filter.Comparison.BETWEEN,"IS NULL":OpenLayers.Filter.Comparison.IS_NULL},e={},f={AND:OpenLayers.Filter.Logical.AND,OR:OpenLayers.Filter.Logical.OR},g={},h={RPAREN:3,LOGICAL:2,COMPARISON:1},k;for(k in d)d.hasOwnProperty(k)&&(e[d[k]]=k);for(k in f)f.hasOwnProperty(k)&&(g[f[k]]=k);return OpenLayers.Class(OpenLayers.Format,{read:function(d){var e=d;d=[];var f,g=["NOT","GEOMETRY","SPATIAL",
3060 "PROPERTY","LPAREN"];do{a:{f=g;for(var h=void 0,g=void 0,k=f.length,h=0;h<k;h++){var g=f[h],s=b[g]instanceof RegExp?b[g].exec(e):(0,b[g])(e);if(s){f=s[0];e=e.substr(f.length).replace(/^\s*/,"");f={type:g,text:f,remainder:e};break a}}d="ERROR: In parsing: ["+e+"], expected one of: ";for(h=0;h<k;h++)g=f[h],d+="\n "+g+": "+b[g];throw Error(d);}e=f.remainder;g=c[f.type];if("END"!=f.type&&!g)throw Error("No follows list for "+f.type);d.push(f)}while("END"!=f.type);d=a(d);this.keepData&&(this.data=d);
3061 return d},write:function(a){if(a instanceof OpenLayers.Geometry)return a.toString();switch(a.CLASS_NAME){case "OpenLayers.Filter.Spatial":switch(a.type){case OpenLayers.Filter.Spatial.BBOX:return"BBOX("+a.property+","+a.value.toBBOX()+")";case OpenLayers.Filter.Spatial.DWITHIN:return"DWITHIN("+a.property+", "+this.write(a.value)+", "+a.distance+")";case OpenLayers.Filter.Spatial.WITHIN:return"WITHIN("+a.property+", "+this.write(a.value)+")";case OpenLayers.Filter.Spatial.INTERSECTS:return"INTERSECTS("+
3062 a.property+", "+this.write(a.value)+")";case OpenLayers.Filter.Spatial.CONTAINS:return"CONTAINS("+a.property+", "+this.write(a.value)+")";default:throw Error("Unknown spatial filter type: "+a.type);}case "OpenLayers.Filter.Logical":if(a.type==OpenLayers.Filter.Logical.NOT)return"NOT ("+this.write(a.filters[0])+")";for(var b="(",c=!0,d=0;d<a.filters.length;d++)c?c=!1:b+=") "+g[a.type]+" (",b+=this.write(a.filters[d]);return b+")";case "OpenLayers.Filter.Comparison":return a.type==OpenLayers.Filter.Comparison.BETWEEN?
3063 a.property+" BETWEEN "+this.write(a.lowerBoundary)+" AND "+this.write(a.upperBoundary):null!==a.value?a.property+" "+e[a.type]+" "+this.write(a.value):a.property+" "+e[a.type];case void 0:if("string"===typeof a)return"'"+a.replace(/'/g,"''")+"'";if("number"===typeof a)return String(a);default:throw Error("Can't encode: "+a.CLASS_NAME+" "+a);}},CLASS_NAME:"OpenLayers.Format.CQL"})}();OpenLayers.Control.Split=OpenLayers.Class(OpenLayers.Control,{layer:null,source:null,sourceOptions:null,tolerance:null,edge:!0,deferDelete:!1,mutual:!0,targetFilter:null,sourceFilter:null,handler:null,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,[a]);this.options=a||{};this.options.source&&this.setSource(this.options.source)},setSource:function(a){this.active?(this.deactivate(),this.handler&&(this.handler.destroy(),delete this.handler),this.source=a,this.activate()):this.source=
3064 a},activate:function(){var a=OpenLayers.Control.prototype.activate.call(this);if(a)if(!this.source)this.handler||(this.handler=new OpenLayers.Handler.Path(this,{done:function(a){this.onSketchComplete({feature:new OpenLayers.Feature.Vector(a)})}},{layerOptions:this.sourceOptions})),this.handler.activate();else if(this.source.events)this.source.events.on({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});return a},deactivate:function(){var a=OpenLayers.Control.prototype.deactivate.call(this);
3065 a&&this.source&&this.source.events&&this.source.events.un({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});return a},onSketchComplete:function(a){this.feature=null;return!this.considerSplit(a.feature)},afterFeatureModified:function(a){a.modified&&"function"===typeof a.feature.geometry.split&&(this.feature=a.feature,this.considerSplit(a.feature))},removeByGeometry:function(a,b){for(var c=0,d=a.length;c<d;++c)if(a[c].geometry===b){a.splice(c,1);break}},
3066 isEligible:function(a){return a.geometry?a.state!==OpenLayers.State.DELETE&&"function"===typeof a.geometry.split&&this.feature!==a&&(!this.targetFilter||this.targetFilter.evaluate(a.attributes)):!1},considerSplit:function(a){var b=!1,c=!1;if(!this.sourceFilter||this.sourceFilter.evaluate(a.attributes)){for(var d=this.layer&&this.layer.features||[],e,f,g=[],h=[],k=this.layer===this.source&&this.mutual,l={edge:this.edge,tolerance:this.tolerance,mutual:k},m=[a.geometry],n,p,q,r=0,s=d.length;r<s;++r)if(n=
3067 d[r],this.isEligible(n)){p=[n.geometry];for(var t=0;t<m.length;++t){q=m[t];for(var u=0;u<p.length;++u)if(e=p[u],q.getBounds().intersectsBounds(e.getBounds())&&(e=q.split(e,l)))f=this.events.triggerEvent("beforesplit",{source:a,target:n}),!1!==f&&(k&&(f=e[0],1<f.length&&(f.unshift(t,1),Array.prototype.splice.apply(m,f),t+=f.length-3),e=e[1]),1<e.length&&(e.unshift(u,1),Array.prototype.splice.apply(p,e),u+=e.length-3))}p&&1<p.length&&(this.geomsToFeatures(n,p),this.events.triggerEvent("split",{original:n,
3068 features:p}),Array.prototype.push.apply(g,p),h.push(n),c=!0)}m&&1<m.length&&(this.geomsToFeatures(a,m),this.events.triggerEvent("split",{original:a,features:m}),Array.prototype.push.apply(g,m),h.push(a),b=!0);if(b||c){if(this.deferDelete){d=[];r=0;for(s=h.length;r<s;++r)c=h[r],c.state===OpenLayers.State.INSERT?d.push(c):(c.state=OpenLayers.State.DELETE,this.layer.drawFeature(c));this.layer.destroyFeatures(d,{silent:!0});r=0;for(s=g.length;r<s;++r)g[r].state=OpenLayers.State.INSERT}else this.layer.destroyFeatures(h,
3069 {silent:!0});this.layer.addFeatures(g,{silent:!0});this.events.triggerEvent("aftersplit",{source:a,features:g})}}return b},geomsToFeatures:function(a,b){var c=a.clone();delete c.geometry;for(var d,e=0,f=b.length;e<f;++e)d=c.clone(),d.geometry=b[e],d.state=OpenLayers.State.INSERT,b[e]=d},destroy:function(){this.active&&this.deactivate();OpenLayers.Control.prototype.destroy.call(this)},CLASS_NAME:"OpenLayers.Control.Split"});OpenLayers.Layer.WMTS=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,version:"1.0.0",requestEncoding:"KVP",url:null,layer:null,matrixSet:null,style:null,format:"image/jpeg",tileOrigin:null,tileFullExtent:null,formatSuffix:null,matrixIds:null,dimensions:null,params:null,zoomOffset:0,serverResolutions:null,formatSuffixMap:{"image/png":"png","image/png8":"png","image/png24":"png","image/png32":"png",png:"png","image/jpeg":"jpg","image/jpg":"jpg",jpeg:"jpg",jpg:"jpg"},matrix:null,initialize:function(a){var b=
3070 {url:!0,layer:!0,style:!0,matrixSet:!0},c;for(c in b)if(!(c in a))throw Error("Missing property '"+c+"' in layer configuration.");a.params=OpenLayers.Util.upperCaseObject(a.params);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a.name,a.url,a.params,a]);this.formatSuffix||(this.formatSuffix=this.formatSuffixMap[this.format]||this.format.split("/").pop());if(this.matrixIds&&(a=this.matrixIds.length)&&"string"===typeof this.matrixIds[0])for(b=this.matrixIds,this.matrixIds=Array(a),c=0;c<a;++c)this.matrixIds[c]=
3071 {identifier:b[c]}},setMap:function(){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments)},updateMatrixProperties:function(){if(this.matrix=this.getMatrix())this.matrix.topLeftCorner&&(this.tileOrigin=this.matrix.topLeftCorner),this.matrix.tileWidth&&this.matrix.tileHeight&&(this.tileSize=new OpenLayers.Size(this.matrix.tileWidth,this.matrix.tileHeight)),this.tileOrigin||(this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.top)),this.tileFullExtent||(this.tileFullExtent=
3072 this.maxExtent)},moveTo:function(a,b,c){!b&&this.matrix||this.updateMatrixProperties();return OpenLayers.Layer.Grid.prototype.moveTo.apply(this,arguments)},clone:function(a){null==a&&(a=new OpenLayers.Layer.WMTS(this.options));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getIdentifier:function(){return this.getServerZoom()},getMatrix:function(){var a;if(this.matrixIds&&0!==this.matrixIds.length)if("scaleDenominator"in this.matrixIds[0])for(var b=OpenLayers.METERS_PER_INCH*OpenLayers.INCHES_PER_UNIT[this.units]*
3073 this.getServerResolution()/2.8E-4,c=Number.POSITIVE_INFINITY,d,e=0,f=this.matrixIds.length;e<f;++e)d=Math.abs(1-this.matrixIds[e].scaleDenominator/b),d<c&&(c=d,a=this.matrixIds[e]);else a=this.matrixIds[this.getIdentifier()];else a={identifier:this.getIdentifier()};return a},getTileInfo:function(a){var b=this.getServerResolution(),c=(a.lon-this.tileOrigin.lon)/(b*this.tileSize.w);a=(this.tileOrigin.lat-a.lat)/(b*this.tileSize.h);var b=Math.floor(c),d=Math.floor(a);return{col:b,row:d,i:Math.floor((c-
3074 b)*this.tileSize.w),j:Math.floor((a-d)*this.tileSize.h)}},getURL:function(a){a=this.adjustBounds(a);var b="";if(!this.tileFullExtent||this.tileFullExtent.intersectsBounds(a)){a=a.getCenterLonLat();var c=this.getTileInfo(a);a=this.dimensions;var d,b=OpenLayers.Util.isArray(this.url)?this.selectUrl([this.version,this.style,this.matrixSet,this.matrix.identifier,c.row,c.col].join(),this.url):this.url;if("REST"===this.requestEncoding.toUpperCase())if(d=this.params,-1!==b.indexOf("{")){b=b.replace(/\{/g,
3075 "${");c={style:this.style,Style:this.style,TileMatrixSet:this.matrixSet,TileMatrix:this.matrix.identifier,TileRow:c.row,TileCol:c.col};if(a){var e,f;for(f=a.length-1;0<=f;--f)e=a[f],c[e]=d[e.toUpperCase()]}b=OpenLayers.String.format(b,c)}else{e=this.version+"/"+this.layer+"/"+this.style+"/";if(a)for(f=0;f<a.length;f++)d[a[f]]&&(e=e+d[a[f]]+"/");e=e+this.matrixSet+"/"+this.matrix.identifier+"/"+c.row+"/"+c.col+"."+this.formatSuffix;b.match(/\/$/)||(b+="/");b+=e}else"KVP"===this.requestEncoding.toUpperCase()&&
3076 (d={SERVICE:"WMTS",REQUEST:"GetTile",VERSION:this.version,LAYER:this.layer,STYLE:this.style,TILEMATRIXSET:this.matrixSet,TILEMATRIX:this.matrix.identifier,TILEROW:c.row,TILECOL:c.col,FORMAT:this.format},b=OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,[d]))}return b},mergeNewParams:function(a){if("KVP"===this.requestEncoding.toUpperCase())return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,[OpenLayers.Util.upperCaseObject(a)])},CLASS_NAME:"OpenLayers.Layer.WMTS"});OpenLayers.Protocol.SOS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol,{fois:null,formatOptions:null,initialize:function(a){OpenLayers.Protocol.prototype.initialize.apply(this,[a]);a.format||(this.format=new OpenLayers.Format.SOSGetFeatureOfInterest(this.formatOptions))},destroy:function(){this.options&&!this.options.format&&this.format.destroy();this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this)},read:function(a){a=OpenLayers.Util.extend({},a);OpenLayers.Util.applyDefaults(a,this.options||
3077 {});var b=new OpenLayers.Protocol.Response({requestType:"read"}),c=this.format,c=OpenLayers.Format.XML.prototype.write.apply(c,[c.writeNode("sos:GetFeatureOfInterest",{fois:this.fois})]);b.priv=OpenLayers.Request.POST({url:a.url,callback:this.createCallback(this.handleRead,b,a),data:c});return b},handleRead:function(a,b){if(b.callback){var c=a.priv;200<=c.status&&300>c.status?(a.features=this.parseFeatures(c),a.code=OpenLayers.Protocol.Response.SUCCESS):a.code=OpenLayers.Protocol.Response.FAILURE;
3078 b.callback.call(b.scope,a)}},parseFeatures:function(a){var b=a.responseXML;b&&b.documentElement||(b=a.responseText);return!b||0>=b.length?null:this.format.read(b)},CLASS_NAME:"OpenLayers.Protocol.SOS.v1_0_0"});OpenLayers.Layer.KaMapCache=OpenLayers.Class(OpenLayers.Layer.KaMap,{IMAGE_EXTENSIONS:{jpeg:"jpg",gif:"gif",png:"png",png8:"png",png24:"png",dithered:"png"},DEFAULT_FORMAT:"jpeg",initialize:function(a,b,c,d){OpenLayers.Layer.KaMap.prototype.initialize.apply(this,arguments);this.extension=this.IMAGE_EXTENSIONS[this.params.i.toLowerCase()||this.DEFAULT_FORMAT]},getURL:function(a){a=this.adjustBounds(a);var b=this.map.getResolution(),c=Math.round(1E4*this.map.getScale())/1E4,d=Math.round(a.left/b);a=
3079 -Math.round(a.top/b);var b=Math.floor(d/this.tileSize.w/this.params.metaTileSize.w)*this.tileSize.w*this.params.metaTileSize.w,e=Math.floor(a/this.tileSize.h/this.params.metaTileSize.h)*this.tileSize.h*this.params.metaTileSize.h,c=["/",this.params.map,"/",c,"/",this.params.g.replace(/\s/g,"_"),"/def/t",e,"/l",b,"/t",a,"l",d,".",this.extension],d=this.url;OpenLayers.Util.isArray(d)&&(d=this.selectUrl(c.join(""),d));return d+c.join("")},CLASS_NAME:"OpenLayers.Layer.KaMapCache"});OpenLayers.Protocol.WFS.v1_1_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.1.0",initialize:function(a){OpenLayers.Protocol.WFS.v1.prototype.initialize.apply(this,arguments);this.outputFormat&&!this.readFormat&&("gml2"==this.outputFormat.toLowerCase()?this.readFormat=new OpenLayers.Format.GML.v2({featureType:this.featureType,featureNS:this.featureNS,geometryName:this.geometryName}):"json"==this.outputFormat.toLowerCase()&&(this.readFormat=new OpenLayers.Format.GeoJSON))},CLASS_NAME:"OpenLayers.Protocol.WFS.v1_1_0"});OpenLayers.Format.WMSCapabilities.v1_1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.1",readers:{wms:OpenLayers.Util.applyDefaults({SRS:function(a,b){b.srs[this.getChildValue(a)]=!0}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers.wms)},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1"});OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1_1,{version:"1.1.1",profile:"WMSC",readers:{wms:OpenLayers.Util.applyDefaults({VendorSpecificCapabilities:function(a,b){b.vendorSpecific={tileSets:[]};this.readChildNodes(a,b.vendorSpecific)},TileSet:function(a,b){var c={srs:{},bbox:{},resolutions:[]};this.readChildNodes(a,c);b.tileSets.push(c)},Resolutions:function(a,b){for(var c=this.getChildValue(a).split(" "),d=0,e=c.length;d<e;d++)""!=c[d]&&b.resolutions.push(parseFloat(c[d]))},
3080 Width:function(a,b){b.width=parseInt(this.getChildValue(a))},Height:function(a,b){b.height=parseInt(this.getChildValue(a))},Layers:function(a,b){b.layers=this.getChildValue(a)},Styles:function(a,b){b.styles=this.getChildValue(a)}},OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.readers.wms)},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:!0,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[]},destroy:function(){this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({buttonclick:this.onButtonClick,addlayer:this.redraw,changelayer:this.redraw,
3081 removelayer:this.redraw,changebaselayer:this.redraw,scope:this});this.events.unregister("buttonclick",this,this.onButtonClick);OpenLayers.Control.prototype.destroy.apply(this,arguments)},setMap:function(a){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.on({addlayer:this.redraw,changelayer:this.redraw,removelayer:this.redraw,changebaselayer:this.redraw,scope:this});this.outsideViewport?(this.events.attachToElement(this.div),this.events.register("buttonclick",this,this.onButtonClick)):
3082 this.map.events.register("buttonclick",this,this.onButtonClick)},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();this.outsideViewport||this.minimizeControl();this.redraw();return this.div},onButtonClick:function(a){a=a.buttonElement;a===this.minimizeDiv?this.minimizeControl():a===this.maximizeDiv?this.maximizeControl():a._layerSwitcher===this.id&&(a["for"]&&(a=document.getElementById(a["for"])),a.disabled||("radio"==a.type?(a.checked=!0,this.map.setBaseLayer(this.map.getLayer(a._layer))):
3083 (a.checked=!a.checked,this.updateMap())))},clearLayersArray:function(a){this[a+"LayersDiv"].innerHTML="";this[a+"Layers"]=[]},checkRedraw:function(){if(!this.layerStates.length||this.map.layers.length!=this.layerStates.length)return!0;for(var a=0,b=this.layerStates.length;a<b;a++){var c=this.layerStates[a],d=this.map.layers[a];if(c.name!=d.name||c.inRange!=d.inRange||c.id!=d.id||c.visibility!=d.visibility)return!0}return!1},redraw:function(){if(!this.checkRedraw())return this.div;this.clearLayersArray("base");
3084 this.clearLayersArray("data");var a=!1,b=!1,c=this.map.layers.length;this.layerStates=Array(c);for(var d=0;d<c;d++){var e=this.map.layers[d];this.layerStates[d]={name:e.name,visibility:e.visibility,inRange:e.inRange,id:e.id}}var f=this.map.layers.slice();this.ascending||f.reverse();d=0;for(c=f.length;d<c;d++){var e=f[d],g=e.isBaseLayer;if(e.displayInLayerSwitcher){g?b=!0:a=!0;var h=g?e==this.map.baseLayer:e.getVisibility(),k=document.createElement("input"),l=OpenLayers.Util.createUniqueID(this.id+
3085 "_input_");k.id=l;k.name=g?this.id+"_baseLayers":e.name;k.type=g?"radio":"checkbox";k.value=e.name;k.checked=h;k.defaultChecked=h;k.className="olButton";k._layer=e.id;k._layerSwitcher=this.id;g||e.inRange||(k.disabled=!0);h=document.createElement("label");h["for"]=k.id;OpenLayers.Element.addClass(h,"labelSpan olButton");h._layer=e.id;h._layerSwitcher=this.id;g||e.inRange||(h.style.color="gray");h.innerHTML=e.name;h.style.verticalAlign=g?"bottom":"baseline";l=document.createElement("br");(g?this.baseLayers:
3086 this.dataLayers).push({layer:e,inputElem:k,labelSpan:h});e=g?this.baseLayersDiv:this.dataLayersDiv;e.appendChild(k);e.appendChild(h);e.appendChild(l)}}this.dataLbl.style.display=a?"":"none";this.baseLbl.style.display=b?"":"none";return this.div},updateMap:function(){for(var a=0,b=this.baseLayers.length;a<b;a++){var c=this.baseLayers[a];c.inputElem.checked&&this.map.setBaseLayer(c.layer,!1)}a=0;for(b=this.dataLayers.length;a<b;a++)c=this.dataLayers[a],c.layer.setVisibility(c.inputElem.checked)},maximizeControl:function(a){this.div.style.width=
3087 "";this.div.style.height="";this.showControls(!1);null!=a&&OpenLayers.Event.stop(a)},minimizeControl:function(a){this.div.style.width="0px";this.div.style.height="0px";this.showControls(!0);null!=a&&OpenLayers.Event.stop(a)},showControls:function(a){this.maximizeDiv.style.display=a?"":"none";this.minimizeDiv.style.display=a?"none":"";this.layersDiv.style.display=a?"none":""},loadContents:function(){this.layersDiv=document.createElement("div");this.layersDiv.id=this.id+"_layersDiv";OpenLayers.Element.addClass(this.layersDiv,
3088 "layersDiv");this.baseLbl=document.createElement("div");this.baseLbl.innerHTML=OpenLayers.i18n("Base Layer");OpenLayers.Element.addClass(this.baseLbl,"baseLbl");this.baseLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.baseLayersDiv,"baseLayersDiv");this.dataLbl=document.createElement("div");this.dataLbl.innerHTML=OpenLayers.i18n("Overlays");OpenLayers.Element.addClass(this.dataLbl,"dataLbl");this.dataLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.dataLayersDiv,
3089 "dataLayersDiv");this.ascending?(this.layersDiv.appendChild(this.baseLbl),this.layersDiv.appendChild(this.baseLayersDiv),this.layersDiv.appendChild(this.dataLbl),this.layersDiv.appendChild(this.dataLayersDiv)):(this.layersDiv.appendChild(this.dataLbl),this.layersDiv.appendChild(this.dataLayersDiv),this.layersDiv.appendChild(this.baseLbl),this.layersDiv.appendChild(this.baseLayersDiv));this.div.appendChild(this.layersDiv);var a=OpenLayers.Util.getImageLocation("layer-switcher-maximize.png");this.maximizeDiv=
3090 OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MaximizeDiv",null,null,a,"absolute");OpenLayers.Element.addClass(this.maximizeDiv,"maximizeDiv olButton");this.maximizeDiv.style.display="none";this.div.appendChild(this.maximizeDiv);a=OpenLayers.Util.getImageLocation("layer-switcher-minimize.png");this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MinimizeDiv",null,null,a,"absolute");OpenLayers.Element.addClass(this.minimizeDiv,"minimizeDiv olButton");this.minimizeDiv.style.display=
3091 "none";this.div.appendChild(this.minimizeDiv)},CLASS_NAME:"OpenLayers.Control.LayerSwitcher"});OpenLayers.Format.Atom=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{atom:"http://www.w3.org/2005/Atom",georss:"http://www.georss.org/georss"},feedTitle:"untitled",defaultEntryTitle:"untitled",gmlParser:null,xy:!1,read:function(a){"string"==typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));return this.parseFeatures(a)},write:function(a){var b;if(OpenLayers.Util.isArray(a)){b=this.createElementNSPlus("atom:feed");b.appendChild(this.createElementNSPlus("atom:title",{value:this.feedTitle}));
3092 for(var c=0,d=a.length;c<d;c++)b.appendChild(this.buildEntryNode(a[c]))}else b=this.buildEntryNode(a);return OpenLayers.Format.XML.prototype.write.apply(this,[b])},buildContentNode:function(a){var b=this.createElementNSPlus("atom:content",{attributes:{type:a.type||null}});if(a.src)b.setAttribute("src",a.src);else if("text"==a.type||null==a.type)b.appendChild(this.createTextNode(a.value));else if("html"==a.type){if("string"!=typeof a.value)throw"HTML content must be in form of an escaped string";b.appendChild(this.createTextNode(a.value))}else"xhtml"==
3093 a.type?b.appendChild(a.value):"xhtml"==a.type||a.type.match(/(\+|\/)xml$/)?b.appendChild(a.value):b.appendChild(this.createTextNode(a.value));return b},buildEntryNode:function(a){var b=a.attributes,c=b.atom||{},d=this.createElementNSPlus("atom:entry");if(c.authors)for(var e=OpenLayers.Util.isArray(c.authors)?c.authors:[c.authors],f=0,g=e.length;f<g;f++)d.appendChild(this.buildPersonConstructNode("author",e[f]));if(c.categories)for(var e=OpenLayers.Util.isArray(c.categories)?c.categories:[c.categories],
3094 h,f=0,g=e.length;f<g;f++)h=e[f],d.appendChild(this.createElementNSPlus("atom:category",{attributes:{term:h.term,scheme:h.scheme||null,label:h.label||null}}));c.content&&d.appendChild(this.buildContentNode(c.content));if(c.contributors)for(e=OpenLayers.Util.isArray(c.contributors)?c.contributors:[c.contributors],f=0,g=e.length;f<g;f++)d.appendChild(this.buildPersonConstructNode("contributor",e[f]));a.fid&&d.appendChild(this.createElementNSPlus("atom:id",{value:a.fid}));if(c.links)for(e=OpenLayers.Util.isArray(c.links)?
3095 c.links:[c.links],f=0,g=e.length;f<g;f++)h=e[f],d.appendChild(this.createElementNSPlus("atom:link",{attributes:{href:h.href,rel:h.rel||null,type:h.type||null,hreflang:h.hreflang||null,title:h.title||null,length:h.length||null}}));c.published&&d.appendChild(this.createElementNSPlus("atom:published",{value:c.published}));c.rights&&d.appendChild(this.createElementNSPlus("atom:rights",{value:c.rights}));(c.summary||b.description)&&d.appendChild(this.createElementNSPlus("atom:summary",{value:c.summary||
3096 b.description}));d.appendChild(this.createElementNSPlus("atom:title",{value:c.title||b.title||this.defaultEntryTitle}));c.updated&&d.appendChild(this.createElementNSPlus("atom:updated",{value:c.updated}));a.geometry&&(b=this.createElementNSPlus("georss:where"),b.appendChild(this.buildGeometryNode(a.geometry)),d.appendChild(b));return d},initGmlParser:function(){this.gmlParser=new OpenLayers.Format.GML.v3({xy:this.xy,featureNS:"http://example.com#feature",internalProjection:this.internalProjection,
3097 externalProjection:this.externalProjection})},buildGeometryNode:function(a){this.gmlParser||this.initGmlParser();return this.gmlParser.writeNode("feature:_geometry",a).firstChild},buildPersonConstructNode:function(a,b){var c=["uri","email"],d=this.createElementNSPlus("atom:"+a);d.appendChild(this.createElementNSPlus("atom:name",{value:b.name}));for(var e=0,f=c.length;e<f;e++)b[c[e]]&&d.appendChild(this.createElementNSPlus("atom:"+c[e],{value:b[c[e]]}));return d},getFirstChildValue:function(a,b,c,
3098 d){return(a=this.getElementsByTagNameNS(a,b,c))&&0<a.length?this.getChildValue(a[0],d):d},parseFeature:function(a){var b={},c=null,d=null,e=null,f=this.namespaces.atom;this.parsePersonConstructs(a,"author",b);d=this.getElementsByTagNameNS(a,f,"category");0<d.length&&(b.categories=[]);for(var g=0,h=d.length;g<h;g++){c={};c.term=d[g].getAttribute("term");if(e=d[g].getAttribute("scheme"))c.scheme=e;if(e=d[g].getAttribute("label"))c.label=e;b.categories.push(c)}d=this.getElementsByTagNameNS(a,f,"content");
3099 if(0<d.length){c={};if(e=d[0].getAttribute("type"))c.type=e;(e=d[0].getAttribute("src"))?c.src=e:("text"==c.type||"html"==c.type||null==c.type?c.value=this.getFirstChildValue(a,f,"content",null):"xhtml"==c.type||c.type.match(/(\+|\/)xml$/)?c.value=this.getChildEl(d[0]):c.value=this.getFirstChildValue(a,f,"content",null),b.content=c)}this.parsePersonConstructs(a,"contributor",b);b.id=this.getFirstChildValue(a,f,"id",null);d=this.getElementsByTagNameNS(a,f,"link");0<d.length&&(b.links=Array(d.length));
3100 for(var k=["rel","type","hreflang","title","length"],g=0,h=d.length;g<h;g++){c={};c.href=d[g].getAttribute("href");for(var l=0,m=k.length;l<m;l++)(e=d[g].getAttribute(k[l]))&&(c[k[l]]=e);b.links[g]=c}if(c=this.getFirstChildValue(a,f,"published",null))b.published=c;if(c=this.getFirstChildValue(a,f,"rights",null))b.rights=c;if(c=this.getFirstChildValue(a,f,"summary",null))b.summary=c;b.title=this.getFirstChildValue(a,f,"title",null);b.updated=this.getFirstChildValue(a,f,"updated",null);c={title:b.title,
3101 description:b.summary,atom:b};a=this.parseLocations(a)[0];a=new OpenLayers.Feature.Vector(a,c);a.fid=b.id;return a},parseFeatures:function(a){var b=[],c=this.getElementsByTagNameNS(a,this.namespaces.atom,"entry");0==c.length&&(c=[a]);a=0;for(var d=c.length;a<d;a++)b.push(this.parseFeature(c[a]));return b},parseLocations:function(a){var b=this.namespaces.georss,c={components:[]},d=this.getElementsByTagNameNS(a,b,"where");if(d&&0<d.length){this.gmlParser||this.initGmlParser();for(var e=0,f=d.length;e<
3102 f;e++)this.gmlParser.readChildNodes(d[e],c)}c=c.components;if((d=this.getElementsByTagNameNS(a,b,"point"))&&0<d.length)for(e=0,f=d.length;e<f;e++){var g=OpenLayers.String.trim(d[e].firstChild.nodeValue).split(/\s+/);2!=g.length&&(g=OpenLayers.String.trim(d[e].firstChild.nodeValue).split(/\s*,\s*/));c.push(new OpenLayers.Geometry.Point(g[1],g[0]))}var h=this.getElementsByTagNameNS(a,b,"line");if(h&&0<h.length)for(var k,e=0,f=h.length;e<f;e++){d=OpenLayers.String.trim(h[e].firstChild.nodeValue).split(/\s+/);
3103 k=[];for(var l=0,m=d.length;l<m;l+=2)g=new OpenLayers.Geometry.Point(d[l+1],d[l]),k.push(g);c.push(new OpenLayers.Geometry.LineString(k))}if((a=this.getElementsByTagNameNS(a,b,"polygon"))&&0<a.length)for(e=0,f=a.length;e<f;e++){d=OpenLayers.String.trim(a[e].firstChild.nodeValue).split(/\s+/);k=[];l=0;for(m=d.length;l<m;l+=2)g=new OpenLayers.Geometry.Point(d[l+1],d[l]),k.push(g);c.push(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(k)]))}if(this.internalProjection&&this.externalProjection)for(e=
3104 0,f=c.length;e<f;e++)c[e]&&c[e].transform(this.externalProjection,this.internalProjection);return c},parsePersonConstructs:function(a,b,c){var d=[],e=this.namespaces.atom;a=this.getElementsByTagNameNS(a,e,b);for(var f=["uri","email"],g=0,h=a.length;g<h;g++){var k={};k.name=this.getFirstChildValue(a[g],e,"name",null);for(var l=0,m=f.length;l<m;l++){var n=this.getFirstChildValue(a[g],e,f[l],null);n&&(k[f[l]]=n)}d.push(k)}0<d.length&&(c[b+"s"]=d)},CLASS_NAME:"OpenLayers.Format.Atom"});OpenLayers.Control.KeyboardDefaults=OpenLayers.Class(OpenLayers.Control,{autoActivate:!0,slideFactor:75,observeElement:null,draw:function(){this.handler=new OpenLayers.Handler.Keyboard(this,{keydown:this.defaultKeyPress},{observeElement:this.observeElement||document})},defaultKeyPress:function(a){var b,c=!0;b=OpenLayers.Event.element(a);if(!b||"INPUT"!=b.tagName&&"TEXTAREA"!=b.tagName&&"SELECT"!=b.tagName){switch(a.keyCode){case OpenLayers.Event.KEY_LEFT:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Event.KEY_RIGHT:this.map.pan(this.slideFactor,
3105 0);break;case OpenLayers.Event.KEY_UP:this.map.pan(0,-this.slideFactor);break;case OpenLayers.Event.KEY_DOWN:this.map.pan(0,this.slideFactor);break;case 33:b=this.map.getSize();this.map.pan(0,-0.75*b.h);break;case 34:b=this.map.getSize();this.map.pan(0,0.75*b.h);break;case 35:b=this.map.getSize();this.map.pan(0.75*b.w,0);break;case 36:b=this.map.getSize();this.map.pan(-0.75*b.w,0);break;case 43:case 61:case 187:case 107:this.map.zoomIn();break;case 45:case 109:case 189:case 95:this.map.zoomOut();
3106 break;default:c=!1}c&&OpenLayers.Event.stop(a)}},CLASS_NAME:"OpenLayers.Control.KeyboardDefaults"});OpenLayers.Format.WMTSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1_1_0,{version:"1.0.0",namespaces:{ows:"http://www.opengis.net/ows/1.1",wmts:"http://www.opengis.net/wmts/1.0",xlink:"http://www.w3.org/1999/xlink"},yx:null,defaultPrefix:"wmts",initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a]);this.options=a;a=OpenLayers.Util.extend({},OpenLayers.Format.WMTSCapabilities.prototype.yx);this.yx=OpenLayers.Util.extend(a,this.yx)},read:function(a){"string"==
3107 typeof a&&(a=OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);b.version=this.version;return b},readers:{wmts:{Capabilities:function(a,b){this.readChildNodes(a,b)},Contents:function(a,b){b.contents={};b.contents.layers=[];b.contents.tileMatrixSets={};this.readChildNodes(a,b.contents)},Layer:function(a,b){var c={styles:[],formats:[],dimensions:[],tileMatrixSetLinks:[],layers:[]};this.readChildNodes(a,c);b.layers.push(c)},Style:function(a,
3108 b){var c={};c.isDefault="true"===a.getAttribute("isDefault");this.readChildNodes(a,c);b.styles.push(c)},Format:function(a,b){b.formats.push(this.getChildValue(a))},TileMatrixSetLink:function(a,b){var c={};this.readChildNodes(a,c);b.tileMatrixSetLinks.push(c)},TileMatrixSet:function(a,b){if(b.layers){var c={matrixIds:[]};this.readChildNodes(a,c);b.tileMatrixSets[c.identifier]=c}else b.tileMatrixSet=this.getChildValue(a)},TileMatrix:function(a,b){var c={supportedCRS:b.supportedCRS};this.readChildNodes(a,
3109 c);b.matrixIds.push(c)},ScaleDenominator:function(a,b){b.scaleDenominator=parseFloat(this.getChildValue(a))},TopLeftCorner:function(a,b){var c=this.getChildValue(a).split(" "),d;b.supportedCRS&&(d=b.supportedCRS.replace(/urn:ogc:def:crs:(\w+):.+:(\w+)$/,"urn:ogc:def:crs:$1::$2"),d=!!this.yx[d]);b.topLeftCorner=d?new OpenLayers.LonLat(c[1],c[0]):new OpenLayers.LonLat(c[0],c[1])},TileWidth:function(a,b){b.tileWidth=parseInt(this.getChildValue(a))},TileHeight:function(a,b){b.tileHeight=parseInt(this.getChildValue(a))},
3110 MatrixWidth:function(a,b){b.matrixWidth=parseInt(this.getChildValue(a))},MatrixHeight:function(a,b){b.matrixHeight=parseInt(this.getChildValue(a))},ResourceURL:function(a,b){b.resourceUrl=b.resourceUrl||{};var c=a.getAttribute("resourceType");b.resourceUrls||(b.resourceUrls=[]);c=b.resourceUrl[c]={format:a.getAttribute("format"),template:a.getAttribute("template"),resourceType:c};b.resourceUrls.push(c)},WSDL:function(a,b){b.wsdl={};b.wsdl.href=a.getAttribute("xlink:href")},ServiceMetadataURL:function(a,
3111 b){b.serviceMetadataUrl={};b.serviceMetadataUrl.href=a.getAttribute("xlink:href")},LegendURL:function(a,b){b.legend={};b.legend.href=a.getAttribute("xlink:href");b.legend.format=a.getAttribute("format")},Dimension:function(a,b){var c={values:[]};this.readChildNodes(a,c);b.dimensions.push(c)},Default:function(a,b){b["default"]=this.getChildValue(a)},Value:function(a,b){b.values.push(this.getChildValue(a))}},ows:OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities.v1_0_0"});
3112 (function(h){h.deparam=function(i,j){var d={},k={"true":!0,"false":!1,"null":null};h.each(i.replace(/\+/g," ").split("&"),function(i,l){var m;var a=l.split("="),c=decodeURIComponent(a[0]),g=d,f=0,b=c.split("]["),e=b.length-1;/\[/.test(b[0])&&/\]$/.test(b[e])?(b[e]=b[e].replace(/\]$/,""),b=b.shift().split("[").concat(b),e=b.length-1):e=0;if(2===a.length)if(a=decodeURIComponent(a[1]),j&&(a=a&&!isNaN(a)?+a:"undefined"===a?void 0:void 0!==k[a]?k[a]:a),e)for(;f<=e;f++)c=""===b[f]?g.length:b[f],m=g[c]=
3113 f<e?g[c]||(b[f+1]&&isNaN(b[f+1])?{}:[]):a,g=m;else h.isArray(d[c])?d[c].push(a):d[c]=void 0!==d[c]?[d[c],a]:a;else c&&(d[c]=j?void 0:"")});return d}})(jQuery);
3114 /*!
3115 *
3116 * jQuery Remember Plugin
3117 * Version 0.1.1
3118 *
3119 * Copyright Nick Dreckshage, licensed GPL & MIT
3120 * https://github.com/ndreckshage/jquery-remember
3121 *
3122 * A fork of jQuery Cookie Plugin
3123 * https://github.com/carhartl/jquery-cookie
3124 * Copyright Klaus Hartl
3125 * Released under the MIT licensed
3126 *
3127 */
3128
3129 (function($){
3130
3131 // recommend changing to return function(options) { if using require.js...
3132 $.remember = function(options){
3133 var settings,
3134 remember,
3135 controller;
3136
3137 settings = $.extend({
3138 name: null, // name/key of the cookie/localstorage item
3139 value: undefined, // value pair of cookie/localstorage
3140 getSet: false, // if true, will get if available, set if not. default is to just get OR set
3141 remove: false, // if true, will remove based on name/key
3142 use: 'default', // whether to use localstorage or cookies. default localstorage with cookie fallback.
3143 expires: null, // forces cookie (invalid localstorage attribue).
3144 path: null, // forces cookie.
3145 domain: null, // forces cookie.
3146 secure: null, // forces cookie.
3147 json: false, // will convert to json when set. parse with get.
3148 fallback: true, // whether to fallback to cookies if localstorage not available.
3149 raw: false, // if true, will skip uri encoding/decoding
3150 modernizr: false // set true if youd rather handle localstorage detection through modernizr
3151 }, options);
3152
3153 remember = {
3154 init: function(){
3155 var controller;
3156
3157 // controls what to do with the input. set - get - set/get - erase
3158 // set if name exists, value exists, and not set to remove cookie.
3159 // get if name exists, value does not exist, and not set to remove
3160 // remove if remove set to true
3161 if (settings.name !== null && settings.value !== undefined && settings.remove !== true){
3162 if (settings.getSet === true){
3163 var get = this.get();
3164 // if the value of get exists, return it. otherwise, set the value as specified.
3165 if (get === null){
3166 this.set();
3167 } else {
3168 controller = get;
3169 }
3170 } else {
3171 this.set();
3172 }
3173 } else if (settings.name !== null && settings.value === undefined && settings.remove !== true){
3174 controller = this.get();
3175 } else if (settings.name !== null && settings.remove === true){
3176 this.erase();
3177 }
3178
3179 // will return result of everything to calling js
3180 return controller;
3181 },
3182 get: function(){
3183 var use = this._use(),
3184 value = null,
3185 cookies,
3186 parts,
3187 name;
3188
3189 // grab the key value pair from localstorage
3190 if (use === 'localstorage') {
3191 value = localStorage.getItem(settings.name);
3192 }
3193
3194 // hit if cookie requested, and when double checking a get on an empty localstorage item
3195 if ((use === 'cookie') || (use === 'localstorage' && value === null && settings.fallback !== false)) {
3196
3197 // grab all the cookies from the browser, check if set, and loop through
3198 cookies = document.cookie ? document.cookie : null;
3199 if (cookies !== null){
3200 cookies = cookies.split(';');
3201 for (var i = 0; i < cookies.length; i++){
3202 // separate the key value pair
3203 parts = cookies[i].split('=');
3204 // set name and value to split parts, cleaning up whitespace
3205 name = parts.shift();
3206 name = settings.raw === false ? this._trim(this._decode(name)) : this._trim(name);
3207 value = parts[0];
3208 // break when we hit a match, or cookie is empty
3209 if (settings.name === name) {
3210 break;
3211 } else if (settings.fallback !== false) {
3212 value = localStorage.getItem(settings.name) || null;
3213 } else {
3214 value = null;
3215 }
3216 }
3217 }
3218 }
3219
3220 // decode uri and if json is requested, parse the cookie/localstorage and return to controller
3221 value = (value && settings.raw === false) ? this._decode(value) : value;
3222 value = (value && settings.json === true) ? JSON.parse(value) : value;
3223
3224 return value;
3225 },
3226 set: function(){
3227 var use = this._use();
3228
3229 // if set is hit, user has intentionally tried to set (get/set not hit)
3230 // clear the storage alternative, so the same value isnt stored in both
3231 this.erase();
3232
3233 // convert the value to store in json if requested
3234 settings.value = settings.json === true ? JSON.stringify(settings.value) : settings.value;
3235
3236 // encode
3237 settings.name = settings.raw === false ? encodeURIComponent(settings.name) : settings.name;
3238 settings.value = settings.raw === false ? encodeURIComponent(settings.value) : settings.value;
3239
3240 // store the key value pair in appropriate storage. set unless storage requirements failed
3241 if (use === 'localstorage'){
3242 localStorage.setItem(settings.name, settings.value);
3243 } else if (use !== false){
3244 // convert values that cant be stored and set
3245 settings.value = settings.value === null ? 'null' : settings.value;
3246 this._setCookie();
3247 }
3248 },
3249 erase: function(){
3250 var use = this._use();
3251
3252 // clear localstorage and cookies by setting expiration to negative
3253 if (use !== 'cookie' || settings.fallback !== false){
3254 localStorage.removeItem(settings.name);
3255 }
3256 if (use !== 'localstorage' || settings.fallback !== false){
3257 this._setCookie('', -1);
3258 }
3259 },
3260 _use: function(){
3261 var use,
3262 localStorageSupport = this._localStorage();
3263
3264 // if cookie requested, or any options set that only apply to cookies
3265 if (settings.use === 'cookie' || settings.expires !== null || settings.path !== null || settings.domain !== null || settings.secure !== null){
3266 use = 'cookie';
3267 } else {
3268 // use local storage if available
3269 if (localStorageSupport){
3270 use = 'localstorage';
3271 } else if (settings.fallback !== false) {
3272 // default to cookie, unless fallback banned
3273 use = 'cookie';
3274 } else {
3275 // if all this fails, nothing can be set
3276 use = false;
3277 }
3278 }
3279
3280 return use;
3281 },
3282 _setCookie: function(){
3283 // allow for varying parameters with defaults. value then expires as optional params
3284 var value = arguments.length > 0 ? arguments[0] : settings.value,
3285 expires = arguments.length > 1 ? arguments[1] : settings.expires,
3286 expire;
3287
3288 // set a date in the future (or negative to delete) based on expires date offset
3289 if (typeof expires === 'number') {
3290 expire = new Date();
3291 expire.setDate(expire.getDate() + expires);
3292 }
3293
3294 // set the cookies with all the varying settings
3295 document.cookie = [
3296 settings.name,
3297 '=',
3298 value,
3299 expire ? '; expires=' + expire.toUTCString() : '',
3300 settings.path ? '; path=' + settings.path : '',
3301 settings.domain ? '; domain=' + settings.domain : '',
3302 settings.secure ? '; secure' : ''
3303 ].join('');
3304 },
3305 _localStorage: function(){
3306 if (settings.modernizr === true && typeof Modernizr !== 'undefined'){
3307 return Modernizr.localstorage;
3308 } else {
3309 // check if a browser supports localstorage with simple try catch
3310 try {
3311 localStorage.setItem('jquery-remember-test','jquery-remember-test');
3312 localStorage.removeItem('jquery-remember-test');
3313 return true;
3314 } catch(e){
3315 return false;
3316 }
3317 }
3318 },
3319 _trim: function(s){
3320 // trail a strings leading/ending whitespace
3321 return s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
3322 },
3323 _decode: function(s){
3324 return decodeURIComponent(s.replace(/\+/g, ' '));
3325 }
3326 };
3327
3328 return remember.init();
3329 };
3330
3331 return $.remember;
3332
3333 }(jQuery));
3334 (function(a){if(typeof define==="function"&&define.amd){if(typeof jQuery!=="undefined"){define(["jquery"],a)}else{define([],a)}}else{if(typeof jQuery!=="undefined"){a(jQuery)}else{a()}}})(function(b,e){var q={a:"href",img:"src",form:"action",base:"href",script:"src",iframe:"src",link:"href"},t=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"],p={anchor:"fragment"},a={strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/},s=/^[0-9]+$/;function o(u,x){var z=decodeURI(u),w=a[x||false?"strict":"loose"].exec(z),y={attr:{},param:{},seg:{}},v=14;while(v--){y.attr[t[v]]=w[v]||""}y.param.query=f(y.attr.query);y.param.fragment=f(y.attr.fragment);y.seg.path=y.attr.path.replace(/^\/+|\/+$/g,"").split("/");y.seg.fragment=y.attr.fragment.replace(/^\/+|\/+$/g,"").split("/");y.attr.base=y.attr.host?(y.attr.protocol?y.attr.protocol+"://"+y.attr.host:y.attr.host)+(y.attr.port?":"+y.attr.port:""):"";return y}function m(v){var u=v.tagName;if(typeof u!=="undefined"){return q[u.toLowerCase()]}return u}function c(x,w){if(x[w].length===0){return x[w]={}}var v={};for(var u in x[w]){v[u]=x[w][u]}x[w]=v;return v}function l(y,w,v,z){var u=y.shift();if(!u){if(g(w[v])){w[v].push(z)}else{if("object"==typeof w[v]){w[v]=z}else{if("undefined"==typeof w[v]){w[v]=z}else{w[v]=[w[v],z]}}}}else{var x=w[v]=w[v]||[];if("]"==u){if(g(x)){if(""!=z){x.push(z)}}else{if("object"==typeof x){x[j(x).length]=z}else{x=w[v]=[w[v],z]}}}else{if(~u.indexOf("]")){u=u.substr(0,u.length-1);if(!s.test(u)&&g(x)){x=c(w,v)}l(y,x,u,z)}else{if(!s.test(u)&&g(x)){x=c(w,v)}l(y,x,u,z)}}}}function d(x,w,z){if(~w.indexOf("]")){var y=w.split("[");l(y,x,"base",z)}else{if(!s.test(w)&&g(x.base)){var v={};for(var u in x.base){v[u]=x.base[u]}x.base=v}i(x.base,w,z)}return x}function f(u){if(u==""){return{}}return h(String(u).split(/&|;/),function(v,A){try{A=decodeURIComponent(A.replace(/\+/g," "))}catch(x){}var B=A.indexOf("="),z=n(A),w=A.substr(0,z||B),y=A.substr(z||B,A.length),y=y.substr(y.indexOf("=")+1,y.length);if(""==w){w=A,y=""}return d(v,w,y)},{base:{}}).base}function i(x,w,y){var u=x[w];if(e===u){x[w]=y}else{if(g(u)){u.push(y)}else{x[w]=[u,y]}}}function n(x){var u=x.length,w,y;for(var v=0;v<u;++v){y=x[v];if("]"==y){w=false}if("["==y){w=true}if("="==y&&!w){return v}}}function h(y,v){var w=0,u=y.length>>0,x=arguments[2];while(w<u){if(w in y){x=v.call(e,x,y[w],w,y)}++w}return x}function g(u){return Object.prototype.toString.call(u)==="[object Array]"}function j(v){var u=[];for(prop in v){if(v.hasOwnProperty(prop)){u.push(prop)}}return u}function k(u){return Object(u)===u&&Object.getPrototypeOf(u)===Object.prototype}function r(u,v){if(arguments.length===1&&u===true){v=true;u=e}v=v||false;u=u||window.location.toString();return{data:o(u,v),attr:function(w){w=p[w]||w;return typeof w!=="undefined"?this.data.attr[w]:this.data.attr},param:function(x,w){if(k(x)){this.data.param.query=x;return this}else{if(w==e){return typeof x!=="undefined"?this.data.param.query[x]:this.data.param.query}else{this.data.param.query[x]=w;return this}}},removeParam:function(w){delete this.data.param.query[w]},fparam:function(w){return typeof w!=="undefined"?this.data.param.fragment[w]:this.data.param.fragment},segment:function(w){if(typeof w==="undefined"){return this.data.seg.path}else{w=w<0?this.data.seg.path.length+w:w-1;return this.data.seg.path[w]}},fsegment:function(w){if(typeof w==="undefined"){return this.data.seg.fragment}else{w=w<0?this.data.seg.fragment.length+w:w-1;return this.data.seg.fragment[w]}},toString:function(){var w="";if(this.data.attr.host!==""){w+=this.data.attr.protocol+"://"+this.data.attr.host}if(this.data.attr.port!=="80"){w+=":"+this.data.attr.port}w+=this.data.attr.path;Object.keys=Object.keys||function(C){var A=[];for(var B in C){if(C.hasOwnProperty(B)){A.push(B)}}return A};if(Object.keys(this.data.param.query).length>0){w+="?";var x=[];for(var y in this.data.param.query){x.push(encodeURIComponent(y)+"="+encodeURIComponent(this.data.param.query[y]))}w+=x.join("&")}if(Object.keys(this.data.param.fragment).length>0){w+="#";var z=[];for(var y in this.data.param.fragment){if(this.data.param.fragment[y]===""){z.push(y)}else{z.push(y+"="+this.data.param.fragment[y])}}w+=z.join("&")}return w}}}if(typeof b!=="undefined"){b.fn.url=function(v){var u="";if(this.length){u=b(this).attr(m(this[0]))||""}return r(u,v)};b.url=r}else{window.purl=r}});
3335 /*! jQuery UI - v1.10.3 - 2013-05-29
3336 * http://jqueryui.com
3337 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
3338 * Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
3339
3340 (function( $, undefined ) {
3341
3342 var uuid = 0,
3343 runiqueId = /^ui-id-\d+$/;
3344
3345 // $.ui might exist from components with no dependencies, e.g., $.ui.position
3346 $.ui = $.ui || {};
3347
3348 $.extend( $.ui, {
3349 version: "1.10.3",
3350
3351 keyCode: {
3352 BACKSPACE: 8,
3353 COMMA: 188,
3354 DELETE: 46,
3355 DOWN: 40,
3356 END: 35,
3357 ENTER: 13,
3358 ESCAPE: 27,
3359 HOME: 36,
3360 LEFT: 37,
3361 NUMPAD_ADD: 107,
3362 NUMPAD_DECIMAL: 110,
3363 NUMPAD_DIVIDE: 111,
3364 NUMPAD_ENTER: 108,
3365 NUMPAD_MULTIPLY: 106,
3366 NUMPAD_SUBTRACT: 109,
3367 PAGE_DOWN: 34,
3368 PAGE_UP: 33,
3369 PERIOD: 190,
3370 RIGHT: 39,
3371 SPACE: 32,
3372 TAB: 9,
3373 UP: 38
3374 }
3375 });
3376
3377 // plugins
3378 $.fn.extend({
3379 focus: (function( orig ) {
3380 return function( delay, fn ) {
3381 return typeof delay === "number" ?
3382 this.each(function() {
3383 var elem = this;
3384 setTimeout(function() {
3385 $( elem ).focus();
3386 if ( fn ) {
3387 fn.call( elem );
3388 }
3389 }, delay );
3390 }) :
3391 orig.apply( this, arguments );
3392 };
3393 })( $.fn.focus ),
3394
3395 scrollParent: function() {
3396 var scrollParent;
3397 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
3398 scrollParent = this.parents().filter(function() {
3399 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
3400 }).eq(0);
3401 } else {
3402 scrollParent = this.parents().filter(function() {
3403 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
3404 }).eq(0);
3405 }
3406
3407 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
3408 },
3409
3410 zIndex: function( zIndex ) {
3411 if ( zIndex !== undefined ) {
3412 return this.css( "zIndex", zIndex );
3413 }
3414
3415 if ( this.length ) {
3416 var elem = $( this[ 0 ] ), position, value;
3417 while ( elem.length && elem[ 0 ] !== document ) {
3418 // Ignore z-index if position is set to a value where z-index is ignored by the browser
3419 // This makes behavior of this function consistent across browsers
3420 // WebKit always returns auto if the element is positioned
3421 position = elem.css( "position" );
3422 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3423 // IE returns 0 when zIndex is not specified
3424 // other browsers return a string
3425 // we ignore the case of nested elements with an explicit value of 0
3426 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3427 value = parseInt( elem.css( "zIndex" ), 10 );
3428 if ( !isNaN( value ) && value !== 0 ) {
3429 return value;
3430 }
3431 }
3432 elem = elem.parent();
3433 }
3434 }
3435
3436 return 0;
3437 },
3438
3439 uniqueId: function() {
3440 return this.each(function() {
3441 if ( !this.id ) {
3442 this.id = "ui-id-" + (++uuid);
3443 }
3444 });
3445 },
3446
3447 removeUniqueId: function() {
3448 return this.each(function() {
3449 if ( runiqueId.test( this.id ) ) {
3450 $( this ).removeAttr( "id" );
3451 }
3452 });
3453 }
3454 });
3455
3456 // selectors
3457 function focusable( element, isTabIndexNotNaN ) {
3458 var map, mapName, img,
3459 nodeName = element.nodeName.toLowerCase();
3460 if ( "area" === nodeName ) {
3461 map = element.parentNode;
3462 mapName = map.name;
3463 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3464 return false;
3465 }
3466 img = $( "img[usemap=#" + mapName + "]" )[0];
3467 return !!img && visible( img );
3468 }
3469 return ( /input|select|textarea|button|object/.test( nodeName ) ?
3470 !element.disabled :
3471 "a" === nodeName ?
3472 element.href || isTabIndexNotNaN :
3473 isTabIndexNotNaN) &&
3474 // the element and all of its ancestors must be visible
3475 visible( element );
3476 }
3477
3478 function visible( element ) {
3479 return $.expr.filters.visible( element ) &&
3480 !$( element ).parents().addBack().filter(function() {
3481 return $.css( this, "visibility" ) === "hidden";
3482 }).length;
3483 }
3484
3485 $.extend( $.expr[ ":" ], {
3486 data: $.expr.createPseudo ?
3487 $.expr.createPseudo(function( dataName ) {
3488 return function( elem ) {
3489 return !!$.data( elem, dataName );
3490 };
3491 }) :
3492 // support: jQuery <1.8
3493 function( elem, i, match ) {
3494 return !!$.data( elem, match[ 3 ] );
3495 },
3496
3497 focusable: function( element ) {
3498 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
3499 },
3500
3501 tabbable: function( element ) {
3502 var tabIndex = $.attr( element, "tabindex" ),
3503 isTabIndexNaN = isNaN( tabIndex );
3504 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
3505 }
3506 });
3507
3508 // support: jQuery <1.8
3509 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
3510 $.each( [ "Width", "Height" ], function( i, name ) {
3511 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
3512 type = name.toLowerCase(),
3513 orig = {
3514 innerWidth: $.fn.innerWidth,
3515 innerHeight: $.fn.innerHeight,
3516 outerWidth: $.fn.outerWidth,
3517 outerHeight: $.fn.outerHeight
3518 };
3519
3520 function reduce( elem, size, border, margin ) {
3521 $.each( side, function() {
3522 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
3523 if ( border ) {
3524 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
3525 }
3526 if ( margin ) {
3527 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
3528 }
3529 });
3530 return size;
3531 }
3532
3533 $.fn[ "inner" + name ] = function( size ) {
3534 if ( size === undefined ) {
3535 return orig[ "inner" + name ].call( this );
3536 }
3537
3538 return this.each(function() {
3539 $( this ).css( type, reduce( this, size ) + "px" );
3540 });
3541 };
3542
3543 $.fn[ "outer" + name] = function( size, margin ) {
3544 if ( typeof size !== "number" ) {
3545 return orig[ "outer" + name ].call( this, size );
3546 }
3547
3548 return this.each(function() {
3549 $( this).css( type, reduce( this, size, true, margin ) + "px" );
3550 });
3551 };
3552 });
3553 }
3554
3555 // support: jQuery <1.8
3556 if ( !$.fn.addBack ) {
3557 $.fn.addBack = function( selector ) {
3558 return this.add( selector == null ?
3559 this.prevObject : this.prevObject.filter( selector )
3560 );
3561 };
3562 }
3563
3564 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
3565 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
3566 $.fn.removeData = (function( removeData ) {
3567 return function( key ) {
3568 if ( arguments.length ) {
3569 return removeData.call( this, $.camelCase( key ) );
3570 } else {
3571 return removeData.call( this );
3572 }
3573 };
3574 })( $.fn.removeData );
3575 }
3576
3577
3578
3579
3580
3581 // deprecated
3582 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
3583
3584 $.support.selectstart = "onselectstart" in document.createElement( "div" );
3585 $.fn.extend({
3586 disableSelection: function() {
3587 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
3588 ".ui-disableSelection", function( event ) {
3589 event.preventDefault();
3590 });
3591 },
3592
3593 enableSelection: function() {
3594 return this.unbind( ".ui-disableSelection" );
3595 }
3596 });
3597
3598 $.extend( $.ui, {
3599 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
3600 plugin: {
3601 add: function( module, option, set ) {
3602 var i,
3603 proto = $.ui[ module ].prototype;
3604 for ( i in set ) {
3605 proto.plugins[ i ] = proto.plugins[ i ] || [];
3606 proto.plugins[ i ].push( [ option, set[ i ] ] );
3607 }
3608 },
3609 call: function( instance, name, args ) {
3610 var i,
3611 set = instance.plugins[ name ];
3612 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
3613 return;
3614 }
3615
3616 for ( i = 0; i < set.length; i++ ) {
3617 if ( instance.options[ set[ i ][ 0 ] ] ) {
3618 set[ i ][ 1 ].apply( instance.element, args );
3619 }
3620 }
3621 }
3622 },
3623
3624 // only used by resizable
3625 hasScroll: function( el, a ) {
3626
3627 //If overflow is hidden, the element might have extra content, but the user wants to hide it
3628 if ( $( el ).css( "overflow" ) === "hidden") {
3629 return false;
3630 }
3631
3632 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
3633 has = false;
3634
3635 if ( el[ scroll ] > 0 ) {
3636 return true;
3637 }
3638
3639 // TODO: determine which cases actually cause this to happen
3640 // if the element doesn't have the scroll set, see if it's possible to
3641 // set the scroll
3642 el[ scroll ] = 1;
3643 has = ( el[ scroll ] > 0 );
3644 el[ scroll ] = 0;
3645 return has;
3646 }
3647 });
3648
3649 })( jQuery );
3650 (function( $, undefined ) {
3651
3652 var uuid = 0,
3653 slice = Array.prototype.slice,
3654 _cleanData = $.cleanData;
3655 $.cleanData = function( elems ) {
3656 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
3657 try {
3658 $( elem ).triggerHandler( "remove" );
3659 // http://bugs.jquery.com/ticket/8235
3660 } catch( e ) {}
3661 }
3662 _cleanData( elems );
3663 };
3664
3665 $.widget = function( name, base, prototype ) {
3666 var fullName, existingConstructor, constructor, basePrototype,
3667 // proxiedPrototype allows the provided prototype to remain unmodified
3668 // so that it can be used as a mixin for multiple widgets (#8876)
3669 proxiedPrototype = {},
3670 namespace = name.split( "." )[ 0 ];
3671
3672 name = name.split( "." )[ 1 ];
3673 fullName = namespace + "-" + name;
3674
3675 if ( !prototype ) {
3676 prototype = base;
3677 base = $.Widget;
3678 }
3679
3680 // create selector for plugin
3681 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
3682 return !!$.data( elem, fullName );
3683 };
3684
3685 $[ namespace ] = $[ namespace ] || {};
3686 existingConstructor = $[ namespace ][ name ];
3687 constructor = $[ namespace ][ name ] = function( options, element ) {
3688 // allow instantiation without "new" keyword
3689 if ( !this._createWidget ) {
3690 return new constructor( options, element );
3691 }
3692
3693 // allow instantiation without initializing for simple inheritance
3694 // must use "new" keyword (the code above always passes args)
3695 if ( arguments.length ) {
3696 this._createWidget( options, element );
3697 }
3698 };
3699 // extend with the existing constructor to carry over any static properties
3700 $.extend( constructor, existingConstructor, {
3701 version: prototype.version,
3702 // copy the object used to create the prototype in case we need to
3703 // redefine the widget later
3704 _proto: $.extend( {}, prototype ),
3705 // track widgets that inherit from this widget in case this widget is
3706 // redefined after a widget inherits from it
3707 _childConstructors: []
3708 });
3709
3710 basePrototype = new base();
3711 // we need to make the options hash a property directly on the new instance
3712 // otherwise we'll modify the options hash on the prototype that we're
3713 // inheriting from
3714 basePrototype.options = $.widget.extend( {}, basePrototype.options );
3715 $.each( prototype, function( prop, value ) {
3716 if ( !$.isFunction( value ) ) {
3717 proxiedPrototype[ prop ] = value;
3718 return;
3719 }
3720 proxiedPrototype[ prop ] = (function() {
3721 var _super = function() {
3722 return base.prototype[ prop ].apply( this, arguments );
3723 },
3724 _superApply = function( args ) {
3725 return base.prototype[ prop ].apply( this, args );
3726 };
3727 return function() {
3728 var __super = this._super,
3729 __superApply = this._superApply,
3730 returnValue;
3731
3732 this._super = _super;
3733 this._superApply = _superApply;
3734
3735 returnValue = value.apply( this, arguments );
3736
3737 this._super = __super;
3738 this._superApply = __superApply;
3739
3740 return returnValue;
3741 };
3742 })();
3743 });
3744 constructor.prototype = $.widget.extend( basePrototype, {
3745 // TODO: remove support for widgetEventPrefix
3746 // always use the name + a colon as the prefix, e.g., draggable:start
3747 // don't prefix for widgets that aren't DOM-based
3748 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
3749 }, proxiedPrototype, {
3750 constructor: constructor,
3751 namespace: namespace,
3752 widgetName: name,
3753 widgetFullName: fullName
3754 });
3755
3756 // If this widget is being redefined then we need to find all widgets that
3757 // are inheriting from it and redefine all of them so that they inherit from
3758 // the new version of this widget. We're essentially trying to replace one
3759 // level in the prototype chain.
3760 if ( existingConstructor ) {
3761 $.each( existingConstructor._childConstructors, function( i, child ) {
3762 var childPrototype = child.prototype;
3763
3764 // redefine the child widget using the same prototype that was
3765 // originally used, but inherit from the new version of the base
3766 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
3767 });
3768 // remove the list of existing child constructors from the old constructor
3769 // so the old child constructors can be garbage collected
3770 delete existingConstructor._childConstructors;
3771 } else {
3772 base._childConstructors.push( constructor );
3773 }
3774
3775 $.widget.bridge( name, constructor );
3776 };
3777
3778 $.widget.extend = function( target ) {
3779 var input = slice.call( arguments, 1 ),
3780 inputIndex = 0,
3781 inputLength = input.length,
3782 key,
3783 value;
3784 for ( ; inputIndex < inputLength; inputIndex++ ) {
3785 for ( key in input[ inputIndex ] ) {
3786 value = input[ inputIndex ][ key ];
3787 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
3788 // Clone objects
3789 if ( $.isPlainObject( value ) ) {
3790 target[ key ] = $.isPlainObject( target[ key ] ) ?
3791 $.widget.extend( {}, target[ key ], value ) :
3792 // Don't extend strings, arrays, etc. with objects
3793 $.widget.extend( {}, value );
3794 // Copy everything else by reference
3795 } else {
3796 target[ key ] = value;
3797 }
3798 }
3799 }
3800 }
3801 return target;
3802 };
3803
3804 $.widget.bridge = function( name, object ) {
3805 var fullName = object.prototype.widgetFullName || name;
3806 $.fn[ name ] = function( options ) {
3807 var isMethodCall = typeof options === "string",
3808 args = slice.call( arguments, 1 ),
3809 returnValue = this;
3810
3811 // allow multiple hashes to be passed on init
3812 options = !isMethodCall && args.length ?
3813 $.widget.extend.apply( null, [ options ].concat(args) ) :
3814 options;
3815
3816 if ( isMethodCall ) {
3817 this.each(function() {
3818 var methodValue,
3819 instance = $.data( this, fullName );
3820 if ( !instance ) {
3821 return $.error( "cannot call methods on " + name + " prior to initialization; " +
3822 "attempted to call method '" + options + "'" );
3823 }
3824 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
3825 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
3826 }
3827 methodValue = instance[ options ].apply( instance, args );
3828 if ( methodValue !== instance && methodValue !== undefined ) {
3829 returnValue = methodValue && methodValue.jquery ?
3830 returnValue.pushStack( methodValue.get() ) :
3831 methodValue;
3832 return false;
3833 }
3834 });
3835 } else {
3836 this.each(function() {
3837 var instance = $.data( this, fullName );
3838 if ( instance ) {
3839 instance.option( options || {} )._init();
3840 } else {
3841 $.data( this, fullName, new object( options, this ) );
3842 }
3843 });
3844 }
3845
3846 return returnValue;
3847 };
3848 };
3849
3850 $.Widget = function( /* options, element */ ) {};
3851 $.Widget._childConstructors = [];
3852
3853 $.Widget.prototype = {
3854 widgetName: "widget",
3855 widgetEventPrefix: "",
3856 defaultElement: "<div>",
3857 options: {
3858 disabled: false,
3859
3860 // callbacks
3861 create: null
3862 },
3863 _createWidget: function( options, element ) {
3864 element = $( element || this.defaultElement || this )[ 0 ];
3865 this.element = $( element );
3866 this.uuid = uuid++;
3867 this.eventNamespace = "." + this.widgetName + this.uuid;
3868 this.options = $.widget.extend( {},
3869 this.options,
3870 this._getCreateOptions(),
3871 options );
3872
3873 this.bindings = $();
3874 this.hoverable = $();
3875 this.focusable = $();
3876
3877 if ( element !== this ) {
3878 $.data( element, this.widgetFullName, this );
3879 this._on( true, this.element, {
3880 remove: function( event ) {
3881 if ( event.target === element ) {
3882 this.destroy();
3883 }
3884 }
3885 });
3886 this.document = $( element.style ?
3887 // element within the document
3888 element.ownerDocument :
3889 // element is window or document
3890 element.document || element );
3891 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
3892 }
3893
3894 this._create();
3895 this._trigger( "create", null, this._getCreateEventData() );
3896 this._init();
3897 },
3898 _getCreateOptions: $.noop,
3899 _getCreateEventData: $.noop,
3900 _create: $.noop,
3901 _init: $.noop,
3902
3903 destroy: function() {
3904 this._destroy();
3905 // we can probably remove the unbind calls in 2.0
3906 // all event bindings should go through this._on()
3907 this.element
3908 .unbind( this.eventNamespace )
3909 // 1.9 BC for #7810
3910 // TODO remove dual storage
3911 .removeData( this.widgetName )
3912 .removeData( this.widgetFullName )
3913 // support: jquery <1.6.3
3914 // http://bugs.jquery.com/ticket/9413
3915 .removeData( $.camelCase( this.widgetFullName ) );
3916 this.widget()
3917 .unbind( this.eventNamespace )
3918 .removeAttr( "aria-disabled" )
3919 .removeClass(
3920 this.widgetFullName + "-disabled " +
3921 "ui-state-disabled" );
3922
3923 // clean up events and states
3924 this.bindings.unbind( this.eventNamespace );
3925 this.hoverable.removeClass( "ui-state-hover" );
3926 this.focusable.removeClass( "ui-state-focus" );
3927 },
3928 _destroy: $.noop,
3929
3930 widget: function() {
3931 return this.element;
3932 },
3933
3934 option: function( key, value ) {
3935 var options = key,
3936 parts,
3937 curOption,
3938 i;
3939
3940 if ( arguments.length === 0 ) {
3941 // don't return a reference to the internal hash
3942 return $.widget.extend( {}, this.options );
3943 }
3944
3945 if ( typeof key === "string" ) {
3946 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
3947 options = {};
3948 parts = key.split( "." );
3949 key = parts.shift();
3950 if ( parts.length ) {
3951 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
3952 for ( i = 0; i < parts.length - 1; i++ ) {
3953 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
3954 curOption = curOption[ parts[ i ] ];
3955 }
3956 key = parts.pop();
3957 if ( value === undefined ) {
3958 return curOption[ key ] === undefined ? null : curOption[ key ];
3959 }
3960 curOption[ key ] = value;
3961 } else {
3962 if ( value === undefined ) {
3963 return this.options[ key ] === undefined ? null : this.options[ key ];
3964 }
3965 options[ key ] = value;
3966 }
3967 }
3968
3969 this._setOptions( options );
3970
3971 return this;
3972 },
3973 _setOptions: function( options ) {
3974 var key;
3975
3976 for ( key in options ) {
3977 this._setOption( key, options[ key ] );
3978 }
3979
3980 return this;
3981 },
3982 _setOption: function( key, value ) {
3983 this.options[ key ] = value;
3984
3985 if ( key === "disabled" ) {
3986 this.widget()
3987 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
3988 .attr( "aria-disabled", value );
3989 this.hoverable.removeClass( "ui-state-hover" );
3990 this.focusable.removeClass( "ui-state-focus" );
3991 }
3992
3993 return this;
3994 },
3995
3996 enable: function() {
3997 return this._setOption( "disabled", false );
3998 },
3999 disable: function() {
4000 return this._setOption( "disabled", true );
4001 },
4002
4003 _on: function( suppressDisabledCheck, element, handlers ) {
4004 var delegateElement,
4005 instance = this;
4006
4007 // no suppressDisabledCheck flag, shuffle arguments
4008 if ( typeof suppressDisabledCheck !== "boolean" ) {
4009 handlers = element;
4010 element = suppressDisabledCheck;
4011 suppressDisabledCheck = false;
4012 }
4013
4014 // no element argument, shuffle and use this.element
4015 if ( !handlers ) {
4016 handlers = element;
4017 element = this.element;
4018 delegateElement = this.widget();
4019 } else {
4020 // accept selectors, DOM elements
4021 element = delegateElement = $( element );
4022 this.bindings = this.bindings.add( element );
4023 }
4024
4025 $.each( handlers, function( event, handler ) {
4026 function handlerProxy() {
4027 // allow widgets to customize the disabled handling
4028 // - disabled as an array instead of boolean
4029 // - disabled class as method for disabling individual parts
4030 if ( !suppressDisabledCheck &&
4031 ( instance.options.disabled === true ||
4032 $( this ).hasClass( "ui-state-disabled" ) ) ) {
4033 return;
4034 }
4035 return ( typeof handler === "string" ? instance[ handler ] : handler )
4036 .apply( instance, arguments );
4037 }
4038
4039 // copy the guid so direct unbinding works
4040 if ( typeof handler !== "string" ) {
4041 handlerProxy.guid = handler.guid =
4042 handler.guid || handlerProxy.guid || $.guid++;
4043 }
4044
4045 var match = event.match( /^(\w+)\s*(.*)$/ ),
4046 eventName = match[1] + instance.eventNamespace,
4047 selector = match[2];
4048 if ( selector ) {
4049 delegateElement.delegate( selector, eventName, handlerProxy );
4050 } else {
4051 element.bind( eventName, handlerProxy );
4052 }
4053 });
4054 },
4055
4056 _off: function( element, eventName ) {
4057 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
4058 element.unbind( eventName ).undelegate( eventName );
4059 },
4060
4061 _delay: function( handler, delay ) {
4062 function handlerProxy() {
4063 return ( typeof handler === "string" ? instance[ handler ] : handler )
4064 .apply( instance, arguments );
4065 }
4066 var instance = this;
4067 return setTimeout( handlerProxy, delay || 0 );
4068 },
4069
4070 _hoverable: function( element ) {
4071 this.hoverable = this.hoverable.add( element );
4072 this._on( element, {
4073 mouseenter: function( event ) {
4074 $( event.currentTarget ).addClass( "ui-state-hover" );
4075 },
4076 mouseleave: function( event ) {
4077 $( event.currentTarget ).removeClass( "ui-state-hover" );
4078 }
4079 });
4080 },
4081
4082 _focusable: function( element ) {
4083 this.focusable = this.focusable.add( element );
4084 this._on( element, {
4085 focusin: function( event ) {
4086 $( event.currentTarget ).addClass( "ui-state-focus" );
4087 },
4088 focusout: function( event ) {
4089 $( event.currentTarget ).removeClass( "ui-state-focus" );
4090 }
4091 });
4092 },
4093
4094 _trigger: function( type, event, data ) {
4095 var prop, orig,
4096 callback = this.options[ type ];
4097
4098 data = data || {};
4099 event = $.Event( event );
4100 event.type = ( type === this.widgetEventPrefix ?
4101 type :
4102 this.widgetEventPrefix + type ).toLowerCase();
4103 // the original event may come from any element
4104 // so we need to reset the target on the new event
4105 event.target = this.element[ 0 ];
4106
4107 // copy original event properties over to the new event
4108 orig = event.originalEvent;
4109 if ( orig ) {
4110 for ( prop in orig ) {
4111 if ( !( prop in event ) ) {
4112 event[ prop ] = orig[ prop ];
4113 }
4114 }
4115 }
4116
4117 this.element.trigger( event, data );
4118 return !( $.isFunction( callback ) &&
4119 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
4120 event.isDefaultPrevented() );
4121 }
4122 };
4123
4124 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
4125 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
4126 if ( typeof options === "string" ) {
4127 options = { effect: options };
4128 }
4129 var hasOptions,
4130 effectName = !options ?
4131 method :
4132 options === true || typeof options === "number" ?
4133 defaultEffect :
4134 options.effect || defaultEffect;
4135 options = options || {};
4136 if ( typeof options === "number" ) {
4137 options = { duration: options };
4138 }
4139 hasOptions = !$.isEmptyObject( options );
4140 options.complete = callback;
4141 if ( options.delay ) {
4142 element.delay( options.delay );
4143 }
4144 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
4145 element[ method ]( options );
4146 } else if ( effectName !== method && element[ effectName ] ) {
4147 element[ effectName ]( options.duration, options.easing, callback );
4148 } else {
4149 element.queue(function( next ) {
4150 $( this )[ method ]();
4151 if ( callback ) {
4152 callback.call( element[ 0 ] );
4153 }
4154 next();
4155 });
4156 }
4157 };
4158 });
4159
4160 })( jQuery );
4161 (function( $, undefined ) {
4162
4163 var mouseHandled = false;
4164 $( document ).mouseup( function() {
4165 mouseHandled = false;
4166 });
4167
4168 $.widget("ui.mouse", {
4169 version: "1.10.3",
4170 options: {
4171 cancel: "input,textarea,button,select,option",
4172 distance: 1,
4173 delay: 0
4174 },
4175 _mouseInit: function() {
4176 var that = this;
4177
4178 this.element
4179 .bind("mousedown."+this.widgetName, function(event) {
4180 return that._mouseDown(event);
4181 })
4182 .bind("click."+this.widgetName, function(event) {
4183 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
4184 $.removeData(event.target, that.widgetName + ".preventClickEvent");
4185 event.stopImmediatePropagation();
4186 return false;
4187 }
4188 });
4189
4190 this.started = false;
4191 },
4192
4193 // TODO: make sure destroying one instance of mouse doesn't mess with
4194 // other instances of mouse
4195 _mouseDestroy: function() {
4196 this.element.unbind("."+this.widgetName);
4197 if ( this._mouseMoveDelegate ) {
4198 $(document)
4199 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
4200 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
4201 }
4202 },
4203
4204 _mouseDown: function(event) {
4205 // don't let more than one widget handle mouseStart
4206 if( mouseHandled ) { return; }
4207
4208 // we may have missed mouseup (out of window)
4209 (this._mouseStarted && this._mouseUp(event));
4210
4211 this._mouseDownEvent = event;
4212
4213 var that = this,
4214 btnIsLeft = (event.which === 1),
4215 // event.target.nodeName works around a bug in IE 8 with
4216 // disabled inputs (#7620)
4217 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
4218 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
4219 return true;
4220 }
4221
4222 this.mouseDelayMet = !this.options.delay;
4223 if (!this.mouseDelayMet) {
4224 this._mouseDelayTimer = setTimeout(function() {
4225 that.mouseDelayMet = true;
4226 }, this.options.delay);
4227 }
4228
4229 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
4230 this._mouseStarted = (this._mouseStart(event) !== false);
4231 if (!this._mouseStarted) {
4232 event.preventDefault();
4233 return true;
4234 }
4235 }
4236
4237 // Click event may never have fired (Gecko & Opera)
4238 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
4239 $.removeData(event.target, this.widgetName + ".preventClickEvent");
4240 }
4241
4242 // these delegates are required to keep context
4243 this._mouseMoveDelegate = function(event) {
4244 return that._mouseMove(event);
4245 };
4246 this._mouseUpDelegate = function(event) {
4247 return that._mouseUp(event);
4248 };
4249 $(document)
4250 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
4251 .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
4252
4253 event.preventDefault();
4254
4255 mouseHandled = true;
4256 return true;
4257 },
4258
4259 _mouseMove: function(event) {
4260 // IE mouseup check - mouseup happened when mouse was out of window
4261 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
4262 return this._mouseUp(event);
4263 }
4264
4265 if (this._mouseStarted) {
4266 this._mouseDrag(event);
4267 return event.preventDefault();
4268 }
4269
4270 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
4271 this._mouseStarted =
4272 (this._mouseStart(this._mouseDownEvent, event) !== false);
4273 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
4274 }
4275
4276 return !this._mouseStarted;
4277 },
4278
4279 _mouseUp: function(event) {
4280 $(document)
4281 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
4282 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
4283
4284 if (this._mouseStarted) {
4285 this._mouseStarted = false;
4286
4287 if (event.target === this._mouseDownEvent.target) {
4288 $.data(event.target, this.widgetName + ".preventClickEvent", true);
4289 }
4290
4291 this._mouseStop(event);
4292 }
4293
4294 return false;
4295 },
4296
4297 _mouseDistanceMet: function(event) {
4298 return (Math.max(
4299 Math.abs(this._mouseDownEvent.pageX - event.pageX),
4300 Math.abs(this._mouseDownEvent.pageY - event.pageY)
4301 ) >= this.options.distance
4302 );
4303 },
4304
4305 _mouseDelayMet: function(/* event */) {
4306 return this.mouseDelayMet;
4307 },
4308
4309 // These are placeholder methods, to be overriden by extending plugin
4310 _mouseStart: function(/* event */) {},
4311 _mouseDrag: function(/* event */) {},
4312 _mouseStop: function(/* event */) {},
4313 _mouseCapture: function(/* event */) { return true; }
4314 });
4315
4316 })(jQuery);
4317 (function( $, undefined ) {
4318
4319 $.ui = $.ui || {};
4320
4321 var cachedScrollbarWidth,
4322 max = Math.max,
4323 abs = Math.abs,
4324 round = Math.round,
4325 rhorizontal = /left|center|right/,
4326 rvertical = /top|center|bottom/,
4327 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
4328 rposition = /^\w+/,
4329 rpercent = /%$/,
4330 _position = $.fn.position;
4331
4332 function getOffsets( offsets, width, height ) {
4333 return [
4334 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
4335 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
4336 ];
4337 }
4338
4339 function parseCss( element, property ) {
4340 return parseInt( $.css( element, property ), 10 ) || 0;
4341 }
4342
4343 function getDimensions( elem ) {
4344 var raw = elem[0];
4345 if ( raw.nodeType === 9 ) {
4346 return {
4347 width: elem.width(),
4348 height: elem.height(),
4349 offset: { top: 0, left: 0 }
4350 };
4351 }
4352 if ( $.isWindow( raw ) ) {
4353 return {
4354 width: elem.width(),
4355 height: elem.height(),
4356 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
4357 };
4358 }
4359 if ( raw.preventDefault ) {
4360 return {
4361 width: 0,
4362 height: 0,
4363 offset: { top: raw.pageY, left: raw.pageX }
4364 };
4365 }
4366 return {
4367 width: elem.outerWidth(),
4368 height: elem.outerHeight(),
4369 offset: elem.offset()
4370 };
4371 }
4372
4373 $.position = {
4374 scrollbarWidth: function() {
4375 if ( cachedScrollbarWidth !== undefined ) {
4376 return cachedScrollbarWidth;
4377 }
4378 var w1, w2,
4379 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
4380 innerDiv = div.children()[0];
4381
4382 $( "body" ).append( div );
4383 w1 = innerDiv.offsetWidth;
4384 div.css( "overflow", "scroll" );
4385
4386 w2 = innerDiv.offsetWidth;
4387
4388 if ( w1 === w2 ) {
4389 w2 = div[0].clientWidth;
4390 }
4391
4392 div.remove();
4393
4394 return (cachedScrollbarWidth = w1 - w2);
4395 },
4396 getScrollInfo: function( within ) {
4397 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
4398 overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
4399 hasOverflowX = overflowX === "scroll" ||
4400 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
4401 hasOverflowY = overflowY === "scroll" ||
4402 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
4403 return {
4404 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
4405 height: hasOverflowX ? $.position.scrollbarWidth() : 0
4406 };
4407 },
4408 getWithinInfo: function( element ) {
4409 var withinElement = $( element || window ),
4410 isWindow = $.isWindow( withinElement[0] );
4411 return {
4412 element: withinElement,
4413 isWindow: isWindow,
4414 offset: withinElement.offset() || { left: 0, top: 0 },
4415 scrollLeft: withinElement.scrollLeft(),
4416 scrollTop: withinElement.scrollTop(),
4417 width: isWindow ? withinElement.width() : withinElement.outerWidth(),
4418 height: isWindow ? withinElement.height() : withinElement.outerHeight()
4419 };
4420 }
4421 };
4422
4423 $.fn.position = function( options ) {
4424 if ( !options || !options.of ) {
4425 return _position.apply( this, arguments );
4426 }
4427
4428 // make a copy, we don't want to modify arguments
4429 options = $.extend( {}, options );
4430
4431 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
4432 target = $( options.of ),
4433 within = $.position.getWithinInfo( options.within ),
4434 scrollInfo = $.position.getScrollInfo( within ),
4435 collision = ( options.collision || "flip" ).split( " " ),
4436 offsets = {};
4437
4438 dimensions = getDimensions( target );
4439 if ( target[0].preventDefault ) {
4440 // force left top to allow flipping
4441 options.at = "left top";
4442 }
4443 targetWidth = dimensions.width;
4444 targetHeight = dimensions.height;
4445 targetOffset = dimensions.offset;
4446 // clone to reuse original targetOffset later
4447 basePosition = $.extend( {}, targetOffset );
4448
4449 // force my and at to have valid horizontal and vertical positions
4450 // if a value is missing or invalid, it will be converted to center
4451 $.each( [ "my", "at" ], function() {
4452 var pos = ( options[ this ] || "" ).split( " " ),
4453 horizontalOffset,
4454 verticalOffset;
4455
4456 if ( pos.length === 1) {
4457 pos = rhorizontal.test( pos[ 0 ] ) ?
4458 pos.concat( [ "center" ] ) :
4459 rvertical.test( pos[ 0 ] ) ?
4460 [ "center" ].concat( pos ) :
4461 [ "center", "center" ];
4462 }
4463 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
4464 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
4465
4466 // calculate offsets
4467 horizontalOffset = roffset.exec( pos[ 0 ] );
4468 verticalOffset = roffset.exec( pos[ 1 ] );
4469 offsets[ this ] = [
4470 horizontalOffset ? horizontalOffset[ 0 ] : 0,
4471 verticalOffset ? verticalOffset[ 0 ] : 0
4472 ];
4473
4474 // reduce to just the positions without the offsets
4475 options[ this ] = [
4476 rposition.exec( pos[ 0 ] )[ 0 ],
4477 rposition.exec( pos[ 1 ] )[ 0 ]
4478 ];
4479 });
4480
4481 // normalize collision option
4482 if ( collision.length === 1 ) {
4483 collision[ 1 ] = collision[ 0 ];
4484 }
4485
4486 if ( options.at[ 0 ] === "right" ) {
4487 basePosition.left += targetWidth;
4488 } else if ( options.at[ 0 ] === "center" ) {
4489 basePosition.left += targetWidth / 2;
4490 }
4491
4492 if ( options.at[ 1 ] === "bottom" ) {
4493 basePosition.top += targetHeight;
4494 } else if ( options.at[ 1 ] === "center" ) {
4495 basePosition.top += targetHeight / 2;
4496 }
4497
4498 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
4499 basePosition.left += atOffset[ 0 ];
4500 basePosition.top += atOffset[ 1 ];
4501
4502 return this.each(function() {
4503 var collisionPosition, using,
4504 elem = $( this ),
4505 elemWidth = elem.outerWidth(),
4506 elemHeight = elem.outerHeight(),
4507 marginLeft = parseCss( this, "marginLeft" ),
4508 marginTop = parseCss( this, "marginTop" ),
4509 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
4510 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
4511 position = $.extend( {}, basePosition ),
4512 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
4513
4514 if ( options.my[ 0 ] === "right" ) {
4515 position.left -= elemWidth;
4516 } else if ( options.my[ 0 ] === "center" ) {
4517 position.left -= elemWidth / 2;
4518 }
4519
4520 if ( options.my[ 1 ] === "bottom" ) {
4521 position.top -= elemHeight;
4522 } else if ( options.my[ 1 ] === "center" ) {
4523 position.top -= elemHeight / 2;
4524 }
4525
4526 position.left += myOffset[ 0 ];
4527 position.top += myOffset[ 1 ];
4528
4529 // if the browser doesn't support fractions, then round for consistent results
4530 if ( !$.support.offsetFractions ) {
4531 position.left = round( position.left );
4532 position.top = round( position.top );
4533 }
4534
4535 collisionPosition = {
4536 marginLeft: marginLeft,
4537 marginTop: marginTop
4538 };
4539
4540 $.each( [ "left", "top" ], function( i, dir ) {
4541 if ( $.ui.position[ collision[ i ] ] ) {
4542 $.ui.position[ collision[ i ] ][ dir ]( position, {
4543 targetWidth: targetWidth,
4544 targetHeight: targetHeight,
4545 elemWidth: elemWidth,
4546 elemHeight: elemHeight,
4547 collisionPosition: collisionPosition,
4548 collisionWidth: collisionWidth,
4549 collisionHeight: collisionHeight,
4550 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
4551 my: options.my,
4552 at: options.at,
4553 within: within,
4554 elem : elem
4555 });
4556 }
4557 });
4558
4559 if ( options.using ) {
4560 // adds feedback as second argument to using callback, if present
4561 using = function( props ) {
4562 var left = targetOffset.left - position.left,
4563 right = left + targetWidth - elemWidth,
4564 top = targetOffset.top - position.top,
4565 bottom = top + targetHeight - elemHeight,
4566 feedback = {
4567 target: {
4568 element: target,
4569 left: targetOffset.left,
4570 top: targetOffset.top,
4571 width: targetWidth,
4572 height: targetHeight
4573 },
4574 element: {
4575 element: elem,
4576 left: position.left,
4577 top: position.top,
4578 width: elemWidth,
4579 height: elemHeight
4580 },
4581 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
4582 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
4583 };
4584 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
4585 feedback.horizontal = "center";
4586 }
4587 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
4588 feedback.vertical = "middle";
4589 }
4590 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
4591 feedback.important = "horizontal";
4592 } else {
4593 feedback.important = "vertical";
4594 }
4595 options.using.call( this, props, feedback );
4596 };
4597 }
4598
4599 elem.offset( $.extend( position, { using: using } ) );
4600 });
4601 };
4602
4603 $.ui.position = {
4604 fit: {
4605 left: function( position, data ) {
4606 var within = data.within,
4607 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
4608 outerWidth = within.width,
4609 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
4610 overLeft = withinOffset - collisionPosLeft,
4611 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
4612 newOverRight;
4613
4614 // element is wider than within
4615 if ( data.collisionWidth > outerWidth ) {
4616 // element is initially over the left side of within
4617 if ( overLeft > 0 && overRight <= 0 ) {
4618 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
4619 position.left += overLeft - newOverRight;
4620 // element is initially over right side of within
4621 } else if ( overRight > 0 && overLeft <= 0 ) {
4622 position.left = withinOffset;
4623 // element is initially over both left and right sides of within
4624 } else {
4625 if ( overLeft > overRight ) {
4626 position.left = withinOffset + outerWidth - data.collisionWidth;
4627 } else {
4628 position.left = withinOffset;
4629 }
4630 }
4631 // too far left -> align with left edge
4632 } else if ( overLeft > 0 ) {
4633 position.left += overLeft;
4634 // too far right -> align with right edge
4635 } else if ( overRight > 0 ) {
4636 position.left -= overRight;
4637 // adjust based on position and margin
4638 } else {
4639 position.left = max( position.left - collisionPosLeft, position.left );
4640 }
4641 },
4642 top: function( position, data ) {
4643 var within = data.within,
4644 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
4645 outerHeight = data.within.height,
4646 collisionPosTop = position.top - data.collisionPosition.marginTop,
4647 overTop = withinOffset - collisionPosTop,
4648 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
4649 newOverBottom;
4650
4651 // element is taller than within
4652 if ( data.collisionHeight > outerHeight ) {
4653 // element is initially over the top of within
4654 if ( overTop > 0 && overBottom <= 0 ) {
4655 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
4656 position.top += overTop - newOverBottom;
4657 // element is initially over bottom of within
4658 } else if ( overBottom > 0 && overTop <= 0 ) {
4659 position.top = withinOffset;
4660 // element is initially over both top and bottom of within
4661 } else {
4662 if ( overTop > overBottom ) {
4663 position.top = withinOffset + outerHeight - data.collisionHeight;
4664 } else {
4665 position.top = withinOffset;
4666 }
4667 }
4668 // too far up -> align with top
4669 } else if ( overTop > 0 ) {
4670 position.top += overTop;
4671 // too far down -> align with bottom edge
4672 } else if ( overBottom > 0 ) {
4673 position.top -= overBottom;
4674 // adjust based on position and margin
4675 } else {
4676 position.top = max( position.top - collisionPosTop, position.top );
4677 }
4678 }
4679 },
4680 flip: {
4681 left: function( position, data ) {
4682 var within = data.within,
4683 withinOffset = within.offset.left + within.scrollLeft,
4684 outerWidth = within.width,
4685 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
4686 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
4687 overLeft = collisionPosLeft - offsetLeft,
4688 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
4689 myOffset = data.my[ 0 ] === "left" ?
4690 -data.elemWidth :
4691 data.my[ 0 ] === "right" ?
4692 data.elemWidth :
4693 0,
4694 atOffset = data.at[ 0 ] === "left" ?
4695 data.targetWidth :
4696 data.at[ 0 ] === "right" ?
4697 -data.targetWidth :
4698 0,
4699 offset = -2 * data.offset[ 0 ],
4700 newOverRight,
4701 newOverLeft;
4702
4703 if ( overLeft < 0 ) {
4704 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
4705 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
4706 position.left += myOffset + atOffset + offset;
4707 }
4708 }
4709 else if ( overRight > 0 ) {
4710 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
4711 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
4712 position.left += myOffset + atOffset + offset;
4713 }
4714 }
4715 },
4716 top: function( position, data ) {
4717 var within = data.within,
4718 withinOffset = within.offset.top + within.scrollTop,
4719 outerHeight = within.height,
4720 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
4721 collisionPosTop = position.top - data.collisionPosition.marginTop,
4722 overTop = collisionPosTop - offsetTop,
4723 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
4724 top = data.my[ 1 ] === "top",
4725 myOffset = top ?
4726 -data.elemHeight :
4727 data.my[ 1 ] === "bottom" ?
4728 data.elemHeight :
4729 0,
4730 atOffset = data.at[ 1 ] === "top" ?
4731 data.targetHeight :
4732 data.at[ 1 ] === "bottom" ?
4733 -data.targetHeight :
4734 0,
4735 offset = -2 * data.offset[ 1 ],
4736 newOverTop,
4737 newOverBottom;
4738 if ( overTop < 0 ) {
4739 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
4740 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
4741 position.top += myOffset + atOffset + offset;
4742 }
4743 }
4744 else if ( overBottom > 0 ) {
4745 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
4746 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
4747 position.top += myOffset + atOffset + offset;
4748 }
4749 }
4750 }
4751 },
4752 flipfit: {
4753 left: function() {
4754 $.ui.position.flip.left.apply( this, arguments );
4755 $.ui.position.fit.left.apply( this, arguments );
4756 },
4757 top: function() {
4758 $.ui.position.flip.top.apply( this, arguments );
4759 $.ui.position.fit.top.apply( this, arguments );
4760 }
4761 }
4762 };
4763
4764 // fraction support test
4765 (function () {
4766 var testElement, testElementParent, testElementStyle, offsetLeft, i,
4767 body = document.getElementsByTagName( "body" )[ 0 ],
4768 div = document.createElement( "div" );
4769
4770 //Create a "fake body" for testing based on method used in jQuery.support
4771 testElement = document.createElement( body ? "div" : "body" );
4772 testElementStyle = {
4773 visibility: "hidden",
4774 width: 0,
4775 height: 0,
4776 border: 0,
4777 margin: 0,
4778 background: "none"
4779 };
4780 if ( body ) {
4781 $.extend( testElementStyle, {
4782 position: "absolute",
4783 left: "-1000px",
4784 top: "-1000px"
4785 });
4786 }
4787 for ( i in testElementStyle ) {
4788 testElement.style[ i ] = testElementStyle[ i ];
4789 }
4790 testElement.appendChild( div );
4791 testElementParent = body || document.documentElement;
4792 testElementParent.insertBefore( testElement, testElementParent.firstChild );
4793
4794 div.style.cssText = "position: absolute; left: 10.7432222px;";
4795
4796 offsetLeft = $( div ).offset().left;
4797 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
4798
4799 testElement.innerHTML = "";
4800 testElementParent.removeChild( testElement );
4801 })();
4802
4803 }( jQuery ) );
4804 (function( $, undefined ) {
4805
4806 $.widget("ui.draggable", $.ui.mouse, {
4807 version: "1.10.3",
4808 widgetEventPrefix: "drag",
4809 options: {
4810 addClasses: true,
4811 appendTo: "parent",
4812 axis: false,
4813 connectToSortable: false,
4814 containment: false,
4815 cursor: "auto",
4816 cursorAt: false,
4817 grid: false,
4818 handle: false,
4819 helper: "original",
4820 iframeFix: false,
4821 opacity: false,
4822 refreshPositions: false,
4823 revert: false,
4824 revertDuration: 500,
4825 scope: "default",
4826 scroll: true,
4827 scrollSensitivity: 20,
4828 scrollSpeed: 20,
4829 snap: false,
4830 snapMode: "both",
4831 snapTolerance: 20,
4832 stack: false,
4833 zIndex: false,
4834
4835 // callbacks
4836 drag: null,
4837 start: null,
4838 stop: null
4839 },
4840 _create: function() {
4841
4842 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
4843 this.element[0].style.position = "relative";
4844 }
4845 if (this.options.addClasses){
4846 this.element.addClass("ui-draggable");
4847 }
4848 if (this.options.disabled){
4849 this.element.addClass("ui-draggable-disabled");
4850 }
4851
4852 this._mouseInit();
4853
4854 },
4855
4856 _destroy: function() {
4857 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
4858 this._mouseDestroy();
4859 },
4860
4861 _mouseCapture: function(event) {
4862
4863 var o = this.options;
4864
4865 // among others, prevent a drag on a resizable-handle
4866 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
4867 return false;
4868 }
4869
4870 //Quit if we're not on a valid handle
4871 this.handle = this._getHandle(event);
4872 if (!this.handle) {
4873 return false;
4874 }
4875
4876 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
4877 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
4878 .css({
4879 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
4880 position: "absolute", opacity: "0.001", zIndex: 1000
4881 })
4882 .css($(this).offset())
4883 .appendTo("body");
4884 });
4885
4886 return true;
4887
4888 },
4889
4890 _mouseStart: function(event) {
4891
4892 var o = this.options;
4893
4894 //Create and append the visible helper
4895 this.helper = this._createHelper(event);
4896
4897 this.helper.addClass("ui-draggable-dragging");
4898
4899 //Cache the helper size
4900 this._cacheHelperProportions();
4901
4902 //If ddmanager is used for droppables, set the global draggable
4903 if($.ui.ddmanager) {
4904 $.ui.ddmanager.current = this;
4905 }
4906
4907 /*
4908 * - Position generation -
4909 * This block generates everything position related - it's the core of draggables.
4910 */
4911
4912 //Cache the margins of the original element
4913 this._cacheMargins();
4914
4915 //Store the helper's css position
4916 this.cssPosition = this.helper.css( "position" );
4917 this.scrollParent = this.helper.scrollParent();
4918 this.offsetParent = this.helper.offsetParent();
4919 this.offsetParentCssPosition = this.offsetParent.css( "position" );
4920
4921 //The element's absolute position on the page minus margins
4922 this.offset = this.positionAbs = this.element.offset();
4923 this.offset = {
4924 top: this.offset.top - this.margins.top,
4925 left: this.offset.left - this.margins.left
4926 };
4927
4928 //Reset scroll cache
4929 this.offset.scroll = false;
4930
4931 $.extend(this.offset, {
4932 click: { //Where the click happened, relative to the element
4933 left: event.pageX - this.offset.left,
4934 top: event.pageY - this.offset.top
4935 },
4936 parent: this._getParentOffset(),
4937 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
4938 });
4939
4940 //Generate the original position
4941 this.originalPosition = this.position = this._generatePosition(event);
4942 this.originalPageX = event.pageX;
4943 this.originalPageY = event.pageY;
4944
4945 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
4946 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
4947
4948 //Set a containment if given in the options
4949 this._setContainment();
4950
4951 //Trigger event + callbacks
4952 if(this._trigger("start", event) === false) {
4953 this._clear();
4954 return false;
4955 }
4956
4957 //Recache the helper size
4958 this._cacheHelperProportions();
4959
4960 //Prepare the droppable offsets
4961 if ($.ui.ddmanager && !o.dropBehaviour) {
4962 $.ui.ddmanager.prepareOffsets(this, event);
4963 }
4964
4965
4966 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
4967
4968 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
4969 if ( $.ui.ddmanager ) {
4970 $.ui.ddmanager.dragStart(this, event);
4971 }
4972
4973 return true;
4974 },
4975
4976 _mouseDrag: function(event, noPropagation) {
4977 // reset any necessary cached properties (see #5009)
4978 if ( this.offsetParentCssPosition === "fixed" ) {
4979 this.offset.parent = this._getParentOffset();
4980 }
4981
4982 //Compute the helpers position
4983 this.position = this._generatePosition(event);
4984 this.positionAbs = this._convertPositionTo("absolute");
4985
4986 //Call plugins and callbacks and use the resulting position if something is returned
4987 if (!noPropagation) {
4988 var ui = this._uiHash();
4989 if(this._trigger("drag", event, ui) === false) {
4990 this._mouseUp({});
4991 return false;
4992 }
4993 this.position = ui.position;
4994 }
4995
4996 if(!this.options.axis || this.options.axis !== "y") {
4997 this.helper[0].style.left = this.position.left+"px";
4998 }
4999 if(!this.options.axis || this.options.axis !== "x") {
5000 this.helper[0].style.top = this.position.top+"px";
5001 }
5002 if($.ui.ddmanager) {
5003 $.ui.ddmanager.drag(this, event);
5004 }
5005
5006 return false;
5007 },
5008
5009 _mouseStop: function(event) {
5010
5011 //If we are using droppables, inform the manager about the drop
5012 var that = this,
5013 dropped = false;
5014 if ($.ui.ddmanager && !this.options.dropBehaviour) {
5015 dropped = $.ui.ddmanager.drop(this, event);
5016 }
5017
5018 //if a drop comes from outside (a sortable)
5019 if(this.dropped) {
5020 dropped = this.dropped;
5021 this.dropped = false;
5022 }
5023
5024 //if the original element is no longer in the DOM don't bother to continue (see #8269)
5025 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
5026 return false;
5027 }
5028
5029 if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
5030 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
5031 if(that._trigger("stop", event) !== false) {
5032 that._clear();
5033 }
5034 });
5035 } else {
5036 if(this._trigger("stop", event) !== false) {
5037 this._clear();
5038 }
5039 }
5040
5041 return false;
5042 },
5043
5044 _mouseUp: function(event) {
5045 //Remove frame helpers
5046 $("div.ui-draggable-iframeFix").each(function() {
5047 this.parentNode.removeChild(this);
5048 });
5049
5050 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
5051 if( $.ui.ddmanager ) {
5052 $.ui.ddmanager.dragStop(this, event);
5053 }
5054
5055 return $.ui.mouse.prototype._mouseUp.call(this, event);
5056 },
5057
5058 cancel: function() {
5059
5060 if(this.helper.is(".ui-draggable-dragging")) {
5061 this._mouseUp({});
5062 } else {
5063 this._clear();
5064 }
5065
5066 return this;
5067
5068 },
5069
5070 _getHandle: function(event) {
5071 return this.options.handle ?
5072 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
5073 true;
5074 },
5075
5076 _createHelper: function(event) {
5077
5078 var o = this.options,
5079 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
5080
5081 if(!helper.parents("body").length) {
5082 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
5083 }
5084
5085 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
5086 helper.css("position", "absolute");
5087 }
5088
5089 return helper;
5090
5091 },
5092
5093 _adjustOffsetFromHelper: function(obj) {
5094 if (typeof obj === "string") {
5095 obj = obj.split(" ");
5096 }
5097 if ($.isArray(obj)) {
5098 obj = {left: +obj[0], top: +obj[1] || 0};
5099 }
5100 if ("left" in obj) {
5101 this.offset.click.left = obj.left + this.margins.left;
5102 }
5103 if ("right" in obj) {
5104 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
5105 }
5106 if ("top" in obj) {
5107 this.offset.click.top = obj.top + this.margins.top;
5108 }
5109 if ("bottom" in obj) {
5110 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
5111 }
5112 },
5113
5114 _getParentOffset: function() {
5115
5116 //Get the offsetParent and cache its position
5117 var po = this.offsetParent.offset();
5118
5119 // This is a special case where we need to modify a offset calculated on start, since the following happened:
5120 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
5121 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
5122 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
5123 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
5124 po.left += this.scrollParent.scrollLeft();
5125 po.top += this.scrollParent.scrollTop();
5126 }
5127
5128 //This needs to be actually done for all browsers, since pageX/pageY includes this information
5129 //Ugly IE fix
5130 if((this.offsetParent[0] === document.body) ||
5131 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
5132 po = { top: 0, left: 0 };
5133 }
5134
5135 return {
5136 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
5137 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
5138 };
5139
5140 },
5141
5142 _getRelativeOffset: function() {
5143
5144 if(this.cssPosition === "relative") {
5145 var p = this.element.position();
5146 return {
5147 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
5148 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
5149 };
5150 } else {
5151 return { top: 0, left: 0 };
5152 }
5153
5154 },
5155
5156 _cacheMargins: function() {
5157 this.margins = {
5158 left: (parseInt(this.element.css("marginLeft"),10) || 0),
5159 top: (parseInt(this.element.css("marginTop"),10) || 0),
5160 right: (parseInt(this.element.css("marginRight"),10) || 0),
5161 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
5162 };
5163 },
5164
5165 _cacheHelperProportions: function() {
5166 this.helperProportions = {
5167 width: this.helper.outerWidth(),
5168 height: this.helper.outerHeight()
5169 };
5170 },
5171
5172 _setContainment: function() {
5173
5174 var over, c, ce,
5175 o = this.options;
5176
5177 if ( !o.containment ) {
5178 this.containment = null;
5179 return;
5180 }
5181
5182 if ( o.containment === "window" ) {
5183 this.containment = [
5184 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
5185 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
5186 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
5187 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
5188 ];
5189 return;
5190 }
5191
5192 if ( o.containment === "document") {
5193 this.containment = [
5194 0,
5195 0,
5196 $( document ).width() - this.helperProportions.width - this.margins.left,
5197 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
5198 ];
5199 return;
5200 }
5201
5202 if ( o.containment.constructor === Array ) {
5203 this.containment = o.containment;
5204 return;
5205 }
5206
5207 if ( o.containment === "parent" ) {
5208 o.containment = this.helper[ 0 ].parentNode;
5209 }
5210
5211 c = $( o.containment );
5212 ce = c[ 0 ];
5213
5214 if( !ce ) {
5215 return;
5216 }
5217
5218 over = c.css( "overflow" ) !== "hidden";
5219
5220 this.containment = [
5221 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
5222 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
5223 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
5224 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom
5225 ];
5226 this.relative_container = c;
5227 },
5228
5229 _convertPositionTo: function(d, pos) {
5230
5231 if(!pos) {
5232 pos = this.position;
5233 }
5234
5235 var mod = d === "absolute" ? 1 : -1,
5236 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
5237
5238 //Cache the scroll
5239 if (!this.offset.scroll) {
5240 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
5241 }
5242
5243 return {
5244 top: (
5245 pos.top + // The absolute mouse position
5246 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5247 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
5248 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
5249 ),
5250 left: (
5251 pos.left + // The absolute mouse position
5252 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5253 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
5254 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
5255 )
5256 };
5257
5258 },
5259
5260 _generatePosition: function(event) {
5261
5262 var containment, co, top, left,
5263 o = this.options,
5264 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
5265 pageX = event.pageX,
5266 pageY = event.pageY;
5267
5268 //Cache the scroll
5269 if (!this.offset.scroll) {
5270 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
5271 }
5272
5273 /*
5274 * - Position constraining -
5275 * Constrain the position to a mix of grid, containment.
5276 */
5277
5278 // If we are not dragging yet, we won't check for options
5279 if ( this.originalPosition ) {
5280 if ( this.containment ) {
5281 if ( this.relative_container ){
5282 co = this.relative_container.offset();
5283 containment = [
5284 this.containment[ 0 ] + co.left,
5285 this.containment[ 1 ] + co.top,
5286 this.containment[ 2 ] + co.left,
5287 this.containment[ 3 ] + co.top
5288 ];
5289 }
5290 else {
5291 containment = this.containment;
5292 }
5293
5294 if(event.pageX - this.offset.click.left < containment[0]) {
5295 pageX = containment[0] + this.offset.click.left;
5296 }
5297 if(event.pageY - this.offset.click.top < containment[1]) {
5298 pageY = containment[1] + this.offset.click.top;
5299 }
5300 if(event.pageX - this.offset.click.left > containment[2]) {
5301 pageX = containment[2] + this.offset.click.left;
5302 }
5303 if(event.pageY - this.offset.click.top > containment[3]) {
5304 pageY = containment[3] + this.offset.click.top;
5305 }
5306 }
5307
5308 if(o.grid) {
5309 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
5310 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
5311 pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
5312
5313 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
5314 pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
5315 }
5316
5317 }
5318
5319 return {
5320 top: (
5321 pageY - // The absolute mouse position
5322 this.offset.click.top - // Click offset (relative to the element)
5323 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
5324 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
5325 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
5326 ),
5327 left: (
5328 pageX - // The absolute mouse position
5329 this.offset.click.left - // Click offset (relative to the element)
5330 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
5331 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
5332 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
5333 )
5334 };
5335
5336 },
5337
5338 _clear: function() {
5339 this.helper.removeClass("ui-draggable-dragging");
5340 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
5341 this.helper.remove();
5342 }
5343 this.helper = null;
5344 this.cancelHelperRemoval = false;
5345 },
5346
5347 // From now on bulk stuff - mainly helpers
5348
5349 _trigger: function(type, event, ui) {
5350 ui = ui || this._uiHash();
5351 $.ui.plugin.call(this, type, [event, ui]);
5352 //The absolute position has to be recalculated after plugins
5353 if(type === "drag") {
5354 this.positionAbs = this._convertPositionTo("absolute");
5355 }
5356 return $.Widget.prototype._trigger.call(this, type, event, ui);
5357 },
5358
5359 plugins: {},
5360
5361 _uiHash: function() {
5362 return {
5363 helper: this.helper,
5364 position: this.position,
5365 originalPosition: this.originalPosition,
5366 offset: this.positionAbs
5367 };
5368 }
5369
5370 });
5371
5372 $.ui.plugin.add("draggable", "connectToSortable", {
5373 start: function(event, ui) {
5374
5375 var inst = $(this).data("ui-draggable"), o = inst.options,
5376 uiSortable = $.extend({}, ui, { item: inst.element });
5377 inst.sortables = [];
5378 $(o.connectToSortable).each(function() {
5379 var sortable = $.data(this, "ui-sortable");
5380 if (sortable && !sortable.options.disabled) {
5381 inst.sortables.push({
5382 instance: sortable,
5383 shouldRevert: sortable.options.revert
5384 });
5385 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
5386 sortable._trigger("activate", event, uiSortable);
5387 }
5388 });
5389
5390 },
5391 stop: function(event, ui) {
5392
5393 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
5394 var inst = $(this).data("ui-draggable"),
5395 uiSortable = $.extend({}, ui, { item: inst.element });
5396
5397 $.each(inst.sortables, function() {
5398 if(this.instance.isOver) {
5399
5400 this.instance.isOver = 0;
5401
5402 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
5403 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
5404
5405 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
5406 if(this.shouldRevert) {
5407 this.instance.options.revert = this.shouldRevert;
5408 }
5409
5410 //Trigger the stop of the sortable
5411 this.instance._mouseStop(event);
5412
5413 this.instance.options.helper = this.instance.options._helper;
5414
5415 //If the helper has been the original item, restore properties in the sortable
5416 if(inst.options.helper === "original") {
5417 this.instance.currentItem.css({ top: "auto", left: "auto" });
5418 }
5419
5420 } else {
5421 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
5422 this.instance._trigger("deactivate", event, uiSortable);
5423 }
5424
5425 });
5426
5427 },
5428 drag: function(event, ui) {
5429
5430 var inst = $(this).data("ui-draggable"), that = this;
5431
5432 $.each(inst.sortables, function() {
5433
5434 var innermostIntersecting = false,
5435 thisSortable = this;
5436
5437 //Copy over some variables to allow calling the sortable's native _intersectsWith
5438 this.instance.positionAbs = inst.positionAbs;
5439 this.instance.helperProportions = inst.helperProportions;
5440 this.instance.offset.click = inst.offset.click;
5441
5442 if(this.instance._intersectsWith(this.instance.containerCache)) {
5443 innermostIntersecting = true;
5444 $.each(inst.sortables, function () {
5445 this.instance.positionAbs = inst.positionAbs;
5446 this.instance.helperProportions = inst.helperProportions;
5447 this.instance.offset.click = inst.offset.click;
5448 if (this !== thisSortable &&
5449 this.instance._intersectsWith(this.instance.containerCache) &&
5450 $.contains(thisSortable.instance.element[0], this.instance.element[0])
5451 ) {
5452 innermostIntersecting = false;
5453 }
5454 return innermostIntersecting;
5455 });
5456 }
5457
5458
5459 if(innermostIntersecting) {
5460 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
5461 if(!this.instance.isOver) {
5462
5463 this.instance.isOver = 1;
5464 //Now we fake the start of dragging for the sortable instance,
5465 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
5466 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
5467 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
5468 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
5469 this.instance.options.helper = function() { return ui.helper[0]; };
5470
5471 event.target = this.instance.currentItem[0];
5472 this.instance._mouseCapture(event, true);
5473 this.instance._mouseStart(event, true, true);
5474
5475 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
5476 this.instance.offset.click.top = inst.offset.click.top;
5477 this.instance.offset.click.left = inst.offset.click.left;
5478 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
5479 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
5480
5481 inst._trigger("toSortable", event);
5482 inst.dropped = this.instance.element; //draggable revert needs that
5483 //hack so receive/update callbacks work (mostly)
5484 inst.currentItem = inst.element;
5485 this.instance.fromOutside = inst;
5486
5487 }
5488
5489 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
5490 if(this.instance.currentItem) {
5491 this.instance._mouseDrag(event);
5492 }
5493
5494 } else {
5495
5496 //If it doesn't intersect with the sortable, and it intersected before,
5497 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
5498 if(this.instance.isOver) {
5499
5500 this.instance.isOver = 0;
5501 this.instance.cancelHelperRemoval = true;
5502
5503 //Prevent reverting on this forced stop
5504 this.instance.options.revert = false;
5505
5506 // The out event needs to be triggered independently
5507 this.instance._trigger("out", event, this.instance._uiHash(this.instance));
5508
5509 this.instance._mouseStop(event, true);
5510 this.instance.options.helper = this.instance.options._helper;
5511
5512 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
5513 this.instance.currentItem.remove();
5514 if(this.instance.placeholder) {
5515 this.instance.placeholder.remove();
5516 }
5517
5518 inst._trigger("fromSortable", event);
5519 inst.dropped = false; //draggable revert needs that
5520 }
5521
5522 }
5523
5524 });
5525
5526 }
5527 });
5528
5529 $.ui.plugin.add("draggable", "cursor", {
5530 start: function() {
5531 var t = $("body"), o = $(this).data("ui-draggable").options;
5532 if (t.css("cursor")) {
5533 o._cursor = t.css("cursor");
5534 }
5535 t.css("cursor", o.cursor);
5536 },
5537 stop: function() {
5538 var o = $(this).data("ui-draggable").options;
5539 if (o._cursor) {
5540 $("body").css("cursor", o._cursor);
5541 }
5542 }
5543 });
5544
5545 $.ui.plugin.add("draggable", "opacity", {
5546 start: function(event, ui) {
5547 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
5548 if(t.css("opacity")) {
5549 o._opacity = t.css("opacity");
5550 }
5551 t.css("opacity", o.opacity);
5552 },
5553 stop: function(event, ui) {
5554 var o = $(this).data("ui-draggable").options;
5555 if(o._opacity) {
5556 $(ui.helper).css("opacity", o._opacity);
5557 }
5558 }
5559 });
5560
5561 $.ui.plugin.add("draggable", "scroll", {
5562 start: function() {
5563 var i = $(this).data("ui-draggable");
5564 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
5565 i.overflowOffset = i.scrollParent.offset();
5566 }
5567 },
5568 drag: function( event ) {
5569
5570 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
5571
5572 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
5573
5574 if(!o.axis || o.axis !== "x") {
5575 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
5576 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
5577 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
5578 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
5579 }
5580 }
5581
5582 if(!o.axis || o.axis !== "y") {
5583 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
5584 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
5585 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
5586 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
5587 }
5588 }
5589
5590 } else {
5591
5592 if(!o.axis || o.axis !== "x") {
5593 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
5594 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
5595 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
5596 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
5597 }
5598 }
5599
5600 if(!o.axis || o.axis !== "y") {
5601 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
5602 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
5603 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
5604 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
5605 }
5606 }
5607
5608 }
5609
5610 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
5611 $.ui.ddmanager.prepareOffsets(i, event);
5612 }
5613
5614 }
5615 });
5616
5617 $.ui.plugin.add("draggable", "snap", {
5618 start: function() {
5619
5620 var i = $(this).data("ui-draggable"),
5621 o = i.options;
5622
5623 i.snapElements = [];
5624
5625 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
5626 var $t = $(this),
5627 $o = $t.offset();
5628 if(this !== i.element[0]) {
5629 i.snapElements.push({
5630 item: this,
5631 width: $t.outerWidth(), height: $t.outerHeight(),
5632 top: $o.top, left: $o.left
5633 });
5634 }
5635 });
5636
5637 },
5638 drag: function(event, ui) {
5639
5640 var ts, bs, ls, rs, l, r, t, b, i, first,
5641 inst = $(this).data("ui-draggable"),
5642 o = inst.options,
5643 d = o.snapTolerance,
5644 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
5645 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
5646
5647 for (i = inst.snapElements.length - 1; i >= 0; i--){
5648
5649 l = inst.snapElements[i].left;
5650 r = l + inst.snapElements[i].width;
5651 t = inst.snapElements[i].top;
5652 b = t + inst.snapElements[i].height;
5653
5654 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
5655 if(inst.snapElements[i].snapping) {
5656 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
5657 }
5658 inst.snapElements[i].snapping = false;
5659 continue;
5660 }
5661
5662 if(o.snapMode !== "inner") {
5663 ts = Math.abs(t - y2) <= d;
5664 bs = Math.abs(b - y1) <= d;
5665 ls = Math.abs(l - x2) <= d;
5666 rs = Math.abs(r - x1) <= d;
5667 if(ts) {
5668 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
5669 }
5670 if(bs) {
5671 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
5672 }
5673 if(ls) {
5674 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
5675 }
5676 if(rs) {
5677 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
5678 }
5679 }
5680
5681 first = (ts || bs || ls || rs);
5682
5683 if(o.snapMode !== "outer") {
5684 ts = Math.abs(t - y1) <= d;
5685 bs = Math.abs(b - y2) <= d;
5686 ls = Math.abs(l - x1) <= d;
5687 rs = Math.abs(r - x2) <= d;
5688 if(ts) {
5689 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
5690 }
5691 if(bs) {
5692 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
5693 }
5694 if(ls) {
5695 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
5696 }
5697 if(rs) {
5698 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
5699 }
5700 }
5701
5702 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
5703 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
5704 }
5705 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
5706
5707 }
5708
5709 }
5710 });
5711
5712 $.ui.plugin.add("draggable", "stack", {
5713 start: function() {
5714 var min,
5715 o = this.data("ui-draggable").options,
5716 group = $.makeArray($(o.stack)).sort(function(a,b) {
5717 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
5718 });
5719
5720 if (!group.length) { return; }
5721
5722 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
5723 $(group).each(function(i) {
5724 $(this).css("zIndex", min + i);
5725 });
5726 this.css("zIndex", (min + group.length));
5727 }
5728 });
5729
5730 $.ui.plugin.add("draggable", "zIndex", {
5731 start: function(event, ui) {
5732 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
5733 if(t.css("zIndex")) {
5734 o._zIndex = t.css("zIndex");
5735 }
5736 t.css("zIndex", o.zIndex);
5737 },
5738 stop: function(event, ui) {
5739 var o = $(this).data("ui-draggable").options;
5740 if(o._zIndex) {
5741 $(ui.helper).css("zIndex", o._zIndex);
5742 }
5743 }
5744 });
5745
5746 })(jQuery);
5747 (function( $, undefined ) {
5748
5749 function isOverAxis( x, reference, size ) {
5750 return ( x > reference ) && ( x < ( reference + size ) );
5751 }
5752
5753 $.widget("ui.droppable", {
5754 version: "1.10.3",
5755 widgetEventPrefix: "drop",
5756 options: {
5757 accept: "*",
5758 activeClass: false,
5759 addClasses: true,
5760 greedy: false,
5761 hoverClass: false,
5762 scope: "default",
5763 tolerance: "intersect",
5764
5765 // callbacks
5766 activate: null,
5767 deactivate: null,
5768 drop: null,
5769 out: null,
5770 over: null
5771 },
5772 _create: function() {
5773
5774 var o = this.options,
5775 accept = o.accept;
5776
5777 this.isover = false;
5778 this.isout = true;
5779
5780 this.accept = $.isFunction(accept) ? accept : function(d) {
5781 return d.is(accept);
5782 };
5783
5784 //Store the droppable's proportions
5785 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
5786
5787 // Add the reference and positions to the manager
5788 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
5789 $.ui.ddmanager.droppables[o.scope].push(this);
5790
5791 (o.addClasses && this.element.addClass("ui-droppable"));
5792
5793 },
5794
5795 _destroy: function() {
5796 var i = 0,
5797 drop = $.ui.ddmanager.droppables[this.options.scope];
5798
5799 for ( ; i < drop.length; i++ ) {
5800 if ( drop[i] === this ) {
5801 drop.splice(i, 1);
5802 }
5803 }
5804
5805 this.element.removeClass("ui-droppable ui-droppable-disabled");
5806 },
5807
5808 _setOption: function(key, value) {
5809
5810 if(key === "accept") {
5811 this.accept = $.isFunction(value) ? value : function(d) {
5812 return d.is(value);
5813 };
5814 }
5815 $.Widget.prototype._setOption.apply(this, arguments);
5816 },
5817
5818 _activate: function(event) {
5819 var draggable = $.ui.ddmanager.current;
5820 if(this.options.activeClass) {
5821 this.element.addClass(this.options.activeClass);
5822 }
5823 if(draggable){
5824 this._trigger("activate", event, this.ui(draggable));
5825 }
5826 },
5827
5828 _deactivate: function(event) {
5829 var draggable = $.ui.ddmanager.current;
5830 if(this.options.activeClass) {
5831 this.element.removeClass(this.options.activeClass);
5832 }
5833 if(draggable){
5834 this._trigger("deactivate", event, this.ui(draggable));
5835 }
5836 },
5837
5838 _over: function(event) {
5839
5840 var draggable = $.ui.ddmanager.current;
5841
5842 // Bail if draggable and droppable are same element
5843 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
5844 return;
5845 }
5846
5847 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
5848 if(this.options.hoverClass) {
5849 this.element.addClass(this.options.hoverClass);
5850 }
5851 this._trigger("over", event, this.ui(draggable));
5852 }
5853
5854 },
5855
5856 _out: function(event) {
5857
5858 var draggable = $.ui.ddmanager.current;
5859
5860 // Bail if draggable and droppable are same element
5861 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
5862 return;
5863 }
5864
5865 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
5866 if(this.options.hoverClass) {
5867 this.element.removeClass(this.options.hoverClass);
5868 }
5869 this._trigger("out", event, this.ui(draggable));
5870 }
5871
5872 },
5873
5874 _drop: function(event,custom) {
5875
5876 var draggable = custom || $.ui.ddmanager.current,
5877 childrenIntersection = false;
5878
5879 // Bail if draggable and droppable are same element
5880 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
5881 return false;
5882 }
5883
5884 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
5885 var inst = $.data(this, "ui-droppable");
5886 if(
5887 inst.options.greedy &&
5888 !inst.options.disabled &&
5889 inst.options.scope === draggable.options.scope &&
5890 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
5891 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
5892 ) { childrenIntersection = true; return false; }
5893 });
5894 if(childrenIntersection) {
5895 return false;
5896 }
5897
5898 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
5899 if(this.options.activeClass) {
5900 this.element.removeClass(this.options.activeClass);
5901 }
5902 if(this.options.hoverClass) {
5903 this.element.removeClass(this.options.hoverClass);
5904 }
5905 this._trigger("drop", event, this.ui(draggable));
5906 return this.element;
5907 }
5908
5909 return false;
5910
5911 },
5912
5913 ui: function(c) {
5914 return {
5915 draggable: (c.currentItem || c.element),
5916 helper: c.helper,
5917 position: c.position,
5918 offset: c.positionAbs
5919 };
5920 }
5921
5922 });
5923
5924 $.ui.intersect = function(draggable, droppable, toleranceMode) {
5925
5926 if (!droppable.offset) {
5927 return false;
5928 }
5929
5930 var draggableLeft, draggableTop,
5931 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
5932 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
5933 l = droppable.offset.left, r = l + droppable.proportions.width,
5934 t = droppable.offset.top, b = t + droppable.proportions.height;
5935
5936 switch (toleranceMode) {
5937 case "fit":
5938 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
5939 case "intersect":
5940 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
5941 x2 - (draggable.helperProportions.width / 2) < r && // Left Half
5942 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
5943 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
5944 case "pointer":
5945 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
5946 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
5947 return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
5948 case "touch":
5949 return (
5950 (y1 >= t && y1 <= b) || // Top edge touching
5951 (y2 >= t && y2 <= b) || // Bottom edge touching
5952 (y1 < t && y2 > b) // Surrounded vertically
5953 ) && (
5954 (x1 >= l && x1 <= r) || // Left edge touching
5955 (x2 >= l && x2 <= r) || // Right edge touching
5956 (x1 < l && x2 > r) // Surrounded horizontally
5957 );
5958 default:
5959 return false;
5960 }
5961
5962 };
5963
5964 /*
5965 This manager tracks offsets of draggables and droppables
5966 */
5967 $.ui.ddmanager = {
5968 current: null,
5969 droppables: { "default": [] },
5970 prepareOffsets: function(t, event) {
5971
5972 var i, j,
5973 m = $.ui.ddmanager.droppables[t.options.scope] || [],
5974 type = event ? event.type : null, // workaround for #2317
5975 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
5976
5977 droppablesLoop: for (i = 0; i < m.length; i++) {
5978
5979 //No disabled and non-accepted
5980 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
5981 continue;
5982 }
5983
5984 // Filter out elements in the current dragged item
5985 for (j=0; j < list.length; j++) {
5986 if(list[j] === m[i].element[0]) {
5987 m[i].proportions.height = 0;
5988 continue droppablesLoop;
5989 }
5990 }
5991
5992 m[i].visible = m[i].element.css("display") !== "none";
5993 if(!m[i].visible) {
5994 continue;
5995 }
5996
5997 //Activate the droppable if used directly from draggables
5998 if(type === "mousedown") {
5999 m[i]._activate.call(m[i], event);
6000 }
6001
6002 m[i].offset = m[i].element.offset();
6003 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
6004
6005 }
6006
6007 },
6008 drop: function(draggable, event) {
6009
6010 var dropped = false;
6011 // Create a copy of the droppables in case the list changes during the drop (#9116)
6012 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
6013
6014 if(!this.options) {
6015 return;
6016 }
6017 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
6018 dropped = this._drop.call(this, event) || dropped;
6019 }
6020
6021 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
6022 this.isout = true;
6023 this.isover = false;
6024 this._deactivate.call(this, event);
6025 }
6026
6027 });
6028 return dropped;
6029
6030 },
6031 dragStart: function( draggable, event ) {
6032 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
6033 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
6034 if( !draggable.options.refreshPositions ) {
6035 $.ui.ddmanager.prepareOffsets( draggable, event );
6036 }
6037 });
6038 },
6039 drag: function(draggable, event) {
6040
6041 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
6042 if(draggable.options.refreshPositions) {
6043 $.ui.ddmanager.prepareOffsets(draggable, event);
6044 }
6045
6046 //Run through all droppables and check their positions based on specific tolerance options
6047 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
6048
6049 if(this.options.disabled || this.greedyChild || !this.visible) {
6050 return;
6051 }
6052
6053 var parentInstance, scope, parent,
6054 intersects = $.ui.intersect(draggable, this, this.options.tolerance),
6055 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
6056 if(!c) {
6057 return;
6058 }
6059
6060 if (this.options.greedy) {
6061 // find droppable parents with same scope
6062 scope = this.options.scope;
6063 parent = this.element.parents(":data(ui-droppable)").filter(function () {
6064 return $.data(this, "ui-droppable").options.scope === scope;
6065 });
6066
6067 if (parent.length) {
6068 parentInstance = $.data(parent[0], "ui-droppable");
6069 parentInstance.greedyChild = (c === "isover");
6070 }
6071 }
6072
6073 // we just moved into a greedy child
6074 if (parentInstance && c === "isover") {
6075 parentInstance.isover = false;
6076 parentInstance.isout = true;
6077 parentInstance._out.call(parentInstance, event);
6078 }
6079
6080 this[c] = true;
6081 this[c === "isout" ? "isover" : "isout"] = false;
6082 this[c === "isover" ? "_over" : "_out"].call(this, event);
6083
6084 // we just moved out of a greedy child
6085 if (parentInstance && c === "isout") {
6086 parentInstance.isout = false;
6087 parentInstance.isover = true;
6088 parentInstance._over.call(parentInstance, event);
6089 }
6090 });
6091
6092 },
6093 dragStop: function( draggable, event ) {
6094 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
6095 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
6096 if( !draggable.options.refreshPositions ) {
6097 $.ui.ddmanager.prepareOffsets( draggable, event );
6098 }
6099 }
6100 };
6101
6102 })(jQuery);
6103 (function( $, undefined ) {
6104
6105 function num(v) {
6106 return parseInt(v, 10) || 0;
6107 }
6108
6109 function isNumber(value) {
6110 return !isNaN(parseInt(value, 10));
6111 }
6112
6113 $.widget("ui.resizable", $.ui.mouse, {
6114 version: "1.10.3",
6115 widgetEventPrefix: "resize",
6116 options: {
6117 alsoResize: false,
6118 animate: false,
6119 animateDuration: "slow",
6120 animateEasing: "swing",
6121 aspectRatio: false,
6122 autoHide: false,
6123 containment: false,
6124 ghost: false,
6125 grid: false,
6126 handles: "e,s,se",
6127 helper: false,
6128 maxHeight: null,
6129 maxWidth: null,
6130 minHeight: 10,
6131 minWidth: 10,
6132 // See #7960
6133 zIndex: 90,
6134
6135 // callbacks
6136 resize: null,
6137 start: null,
6138 stop: null
6139 },
6140 _create: function() {
6141
6142 var n, i, handle, axis, hname,
6143 that = this,
6144 o = this.options;
6145 this.element.addClass("ui-resizable");
6146
6147 $.extend(this, {
6148 _aspectRatio: !!(o.aspectRatio),
6149 aspectRatio: o.aspectRatio,
6150 originalElement: this.element,
6151 _proportionallyResizeElements: [],
6152 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
6153 });
6154
6155 //Wrap the element if it cannot hold child nodes
6156 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
6157
6158 //Create a wrapper element and set the wrapper to the new current internal element
6159 this.element.wrap(
6160 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
6161 position: this.element.css("position"),
6162 width: this.element.outerWidth(),
6163 height: this.element.outerHeight(),
6164 top: this.element.css("top"),
6165 left: this.element.css("left")
6166 })
6167 );
6168
6169 //Overwrite the original this.element
6170 this.element = this.element.parent().data(
6171 "ui-resizable", this.element.data("ui-resizable")
6172 );
6173
6174 this.elementIsWrapper = true;
6175
6176 //Move margins to the wrapper
6177 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
6178 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
6179
6180 //Prevent Safari textarea resize
6181 this.originalResizeStyle = this.originalElement.css("resize");
6182 this.originalElement.css("resize", "none");
6183
6184 //Push the actual element to our proportionallyResize internal array
6185 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
6186
6187 // avoid IE jump (hard set the margin)
6188 this.originalElement.css({ margin: this.originalElement.css("margin") });
6189
6190 // fix handlers offset
6191 this._proportionallyResize();
6192
6193 }
6194
6195 this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
6196 if(this.handles.constructor === String) {
6197
6198 if ( this.handles === "all") {
6199 this.handles = "n,e,s,w,se,sw,ne,nw";
6200 }
6201
6202 n = this.handles.split(",");
6203 this.handles = {};
6204
6205 for(i = 0; i < n.length; i++) {
6206
6207 handle = $.trim(n[i]);
6208 hname = "ui-resizable-"+handle;
6209 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
6210
6211 // Apply zIndex to all handles - see #7960
6212 axis.css({ zIndex: o.zIndex });
6213
6214 //TODO : What's going on here?
6215 if ("se" === handle) {
6216 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
6217 }
6218
6219 //Insert into internal handles object and append to element
6220 this.handles[handle] = ".ui-resizable-"+handle;
6221 this.element.append(axis);
6222 }
6223
6224 }
6225
6226 this._renderAxis = function(target) {
6227
6228 var i, axis, padPos, padWrapper;
6229
6230 target = target || this.element;
6231
6232 for(i in this.handles) {
6233
6234 if(this.handles[i].constructor === String) {
6235 this.handles[i] = $(this.handles[i], this.element).show();
6236 }
6237
6238 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
6239 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
6240
6241 axis = $(this.handles[i], this.element);
6242
6243 //Checking the correct pad and border
6244 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
6245
6246 //The padding type i have to apply...
6247 padPos = [ "padding",
6248 /ne|nw|n/.test(i) ? "Top" :
6249 /se|sw|s/.test(i) ? "Bottom" :
6250 /^e$/.test(i) ? "Right" : "Left" ].join("");
6251
6252 target.css(padPos, padWrapper);
6253
6254 this._proportionallyResize();
6255
6256 }
6257
6258 //TODO: What's that good for? There's not anything to be executed left
6259 if(!$(this.handles[i]).length) {
6260 continue;
6261 }
6262 }
6263 };
6264
6265 //TODO: make renderAxis a prototype function
6266 this._renderAxis(this.element);
6267
6268 this._handles = $(".ui-resizable-handle", this.element)
6269 .disableSelection();
6270
6271 //Matching axis name
6272 this._handles.mouseover(function() {
6273 if (!that.resizing) {
6274 if (this.className) {
6275 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
6276 }
6277 //Axis, default = se
6278 that.axis = axis && axis[1] ? axis[1] : "se";
6279 }
6280 });
6281
6282 //If we want to auto hide the elements
6283 if (o.autoHide) {
6284 this._handles.hide();
6285 $(this.element)
6286 .addClass("ui-resizable-autohide")
6287 .mouseenter(function() {
6288 if (o.disabled) {
6289 return;
6290 }
6291 $(this).removeClass("ui-resizable-autohide");
6292 that._handles.show();
6293 })
6294 .mouseleave(function(){
6295 if (o.disabled) {
6296 return;
6297 }
6298 if (!that.resizing) {
6299 $(this).addClass("ui-resizable-autohide");
6300 that._handles.hide();
6301 }
6302 });
6303 }
6304
6305 //Initialize the mouse interaction
6306 this._mouseInit();
6307
6308 },
6309
6310 _destroy: function() {
6311
6312 this._mouseDestroy();
6313
6314 var wrapper,
6315 _destroy = function(exp) {
6316 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
6317 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
6318 };
6319
6320 //TODO: Unwrap at same DOM position
6321 if (this.elementIsWrapper) {
6322 _destroy(this.element);
6323 wrapper = this.element;
6324 this.originalElement.css({
6325 position: wrapper.css("position"),
6326 width: wrapper.outerWidth(),
6327 height: wrapper.outerHeight(),
6328 top: wrapper.css("top"),
6329 left: wrapper.css("left")
6330 }).insertAfter( wrapper );
6331 wrapper.remove();
6332 }
6333
6334 this.originalElement.css("resize", this.originalResizeStyle);
6335 _destroy(this.originalElement);
6336
6337 return this;
6338 },
6339
6340 _mouseCapture: function(event) {
6341 var i, handle,
6342 capture = false;
6343
6344 for (i in this.handles) {
6345 handle = $(this.handles[i])[0];
6346 if (handle === event.target || $.contains(handle, event.target)) {
6347 capture = true;
6348 }
6349 }
6350
6351 return !this.options.disabled && capture;
6352 },
6353
6354 _mouseStart: function(event) {
6355
6356 var curleft, curtop, cursor,
6357 o = this.options,
6358 iniPos = this.element.position(),
6359 el = this.element;
6360
6361 this.resizing = true;
6362
6363 // bugfix for http://dev.jquery.com/ticket/1749
6364 if ( (/absolute/).test( el.css("position") ) ) {
6365 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
6366 } else if (el.is(".ui-draggable")) {
6367 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
6368 }
6369
6370 this._renderProxy();
6371
6372 curleft = num(this.helper.css("left"));
6373 curtop = num(this.helper.css("top"));
6374
6375 if (o.containment) {
6376 curleft += $(o.containment).scrollLeft() || 0;
6377 curtop += $(o.containment).scrollTop() || 0;
6378 }
6379
6380 //Store needed variables
6381 this.offset = this.helper.offset();
6382 this.position = { left: curleft, top: curtop };
6383 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
6384 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
6385 this.originalPosition = { left: curleft, top: curtop };
6386 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
6387 this.originalMousePosition = { left: event.pageX, top: event.pageY };
6388
6389 //Aspect Ratio
6390 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
6391
6392 cursor = $(".ui-resizable-" + this.axis).css("cursor");
6393 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
6394
6395 el.addClass("ui-resizable-resizing");
6396 this._propagate("start", event);
6397 return true;
6398 },
6399
6400 _mouseDrag: function(event) {
6401
6402 //Increase performance, avoid regex
6403 var data,
6404 el = this.helper, props = {},
6405 smp = this.originalMousePosition,
6406 a = this.axis,
6407 prevTop = this.position.top,
6408 prevLeft = this.position.left,
6409 prevWidth = this.size.width,
6410 prevHeight = this.size.height,
6411 dx = (event.pageX-smp.left)||0,
6412 dy = (event.pageY-smp.top)||0,
6413 trigger = this._change[a];
6414
6415 if (!trigger) {
6416 return false;
6417 }
6418
6419 // Calculate the attrs that will be change
6420 data = trigger.apply(this, [event, dx, dy]);
6421
6422 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
6423 this._updateVirtualBoundaries(event.shiftKey);
6424 if (this._aspectRatio || event.shiftKey) {
6425 data = this._updateRatio(data, event);
6426 }
6427
6428 data = this._respectSize(data, event);
6429
6430 this._updateCache(data);
6431
6432 // plugins callbacks need to be called first
6433 this._propagate("resize", event);
6434
6435 if (this.position.top !== prevTop) {
6436 props.top = this.position.top + "px";
6437 }
6438 if (this.position.left !== prevLeft) {
6439 props.left = this.position.left + "px";
6440 }
6441 if (this.size.width !== prevWidth) {
6442 props.width = this.size.width + "px";
6443 }
6444 if (this.size.height !== prevHeight) {
6445 props.height = this.size.height + "px";
6446 }
6447 el.css(props);
6448
6449 if (!this._helper && this._proportionallyResizeElements.length) {
6450 this._proportionallyResize();
6451 }
6452
6453 // Call the user callback if the element was resized
6454 if ( ! $.isEmptyObject(props) ) {
6455 this._trigger("resize", event, this.ui());
6456 }
6457
6458 return false;
6459 },
6460
6461 _mouseStop: function(event) {
6462
6463 this.resizing = false;
6464 var pr, ista, soffseth, soffsetw, s, left, top,
6465 o = this.options, that = this;
6466
6467 if(this._helper) {
6468
6469 pr = this._proportionallyResizeElements;
6470 ista = pr.length && (/textarea/i).test(pr[0].nodeName);
6471 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
6472 soffsetw = ista ? 0 : that.sizeDiff.width;
6473
6474 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) };
6475 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
6476 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
6477
6478 if (!o.animate) {
6479 this.element.css($.extend(s, { top: top, left: left }));
6480 }
6481
6482 that.helper.height(that.size.height);
6483 that.helper.width(that.size.width);
6484
6485 if (this._helper && !o.animate) {
6486 this._proportionallyResize();
6487 }
6488 }
6489
6490 $("body").css("cursor", "auto");
6491
6492 this.element.removeClass("ui-resizable-resizing");
6493
6494 this._propagate("stop", event);
6495
6496 if (this._helper) {
6497 this.helper.remove();
6498 }
6499
6500 return false;
6501
6502 },
6503
6504 _updateVirtualBoundaries: function(forceAspectRatio) {
6505 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
6506 o = this.options;
6507
6508 b = {
6509 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
6510 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
6511 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
6512 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
6513 };
6514
6515 if(this._aspectRatio || forceAspectRatio) {
6516 // We want to create an enclosing box whose aspect ration is the requested one
6517 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
6518 pMinWidth = b.minHeight * this.aspectRatio;
6519 pMinHeight = b.minWidth / this.aspectRatio;
6520 pMaxWidth = b.maxHeight * this.aspectRatio;
6521 pMaxHeight = b.maxWidth / this.aspectRatio;
6522
6523 if(pMinWidth > b.minWidth) {
6524 b.minWidth = pMinWidth;
6525 }
6526 if(pMinHeight > b.minHeight) {
6527 b.minHeight = pMinHeight;
6528 }
6529 if(pMaxWidth < b.maxWidth) {
6530 b.maxWidth = pMaxWidth;
6531 }
6532 if(pMaxHeight < b.maxHeight) {
6533 b.maxHeight = pMaxHeight;
6534 }
6535 }
6536 this._vBoundaries = b;
6537 },
6538
6539 _updateCache: function(data) {
6540 this.offset = this.helper.offset();
6541 if (isNumber(data.left)) {
6542 this.position.left = data.left;
6543 }
6544 if (isNumber(data.top)) {
6545 this.position.top = data.top;
6546 }
6547 if (isNumber(data.height)) {
6548 this.size.height = data.height;
6549 }
6550 if (isNumber(data.width)) {
6551 this.size.width = data.width;
6552 }
6553 },
6554
6555 _updateRatio: function( data ) {
6556
6557 var cpos = this.position,
6558 csize = this.size,
6559 a = this.axis;
6560
6561 if (isNumber(data.height)) {
6562 data.width = (data.height * this.aspectRatio);
6563 } else if (isNumber(data.width)) {
6564 data.height = (data.width / this.aspectRatio);
6565 }
6566
6567 if (a === "sw") {
6568 data.left = cpos.left + (csize.width - data.width);
6569 data.top = null;
6570 }
6571 if (a === "nw") {
6572 data.top = cpos.top + (csize.height - data.height);
6573 data.left = cpos.left + (csize.width - data.width);
6574 }
6575
6576 return data;
6577 },
6578
6579 _respectSize: function( data ) {
6580
6581 var o = this._vBoundaries,
6582 a = this.axis,
6583 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
6584 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
6585 dw = this.originalPosition.left + this.originalSize.width,
6586 dh = this.position.top + this.size.height,
6587 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
6588 if (isminw) {
6589 data.width = o.minWidth;
6590 }
6591 if (isminh) {
6592 data.height = o.minHeight;
6593 }
6594 if (ismaxw) {
6595 data.width = o.maxWidth;
6596 }
6597 if (ismaxh) {
6598 data.height = o.maxHeight;
6599 }
6600
6601 if (isminw && cw) {
6602 data.left = dw - o.minWidth;
6603 }
6604 if (ismaxw && cw) {
6605 data.left = dw - o.maxWidth;
6606 }
6607 if (isminh && ch) {
6608 data.top = dh - o.minHeight;
6609 }
6610 if (ismaxh && ch) {
6611 data.top = dh - o.maxHeight;
6612 }
6613
6614 // fixing jump error on top/left - bug #2330
6615 if (!data.width && !data.height && !data.left && data.top) {
6616 data.top = null;
6617 } else if (!data.width && !data.height && !data.top && data.left) {
6618 data.left = null;
6619 }
6620
6621 return data;
6622 },
6623
6624 _proportionallyResize: function() {
6625
6626 if (!this._proportionallyResizeElements.length) {
6627 return;
6628 }
6629
6630 var i, j, borders, paddings, prel,
6631 element = this.helper || this.element;
6632
6633 for ( i=0; i < this._proportionallyResizeElements.length; i++) {
6634
6635 prel = this._proportionallyResizeElements[i];
6636
6637 if (!this.borderDif) {
6638 this.borderDif = [];
6639 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
6640 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
6641
6642 for ( j = 0; j < borders.length; j++ ) {
6643 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
6644 }
6645 }
6646
6647 prel.css({
6648 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
6649 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
6650 });
6651
6652 }
6653
6654 },
6655
6656 _renderProxy: function() {
6657
6658 var el = this.element, o = this.options;
6659 this.elementOffset = el.offset();
6660
6661 if(this._helper) {
6662
6663 this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
6664
6665 this.helper.addClass(this._helper).css({
6666 width: this.element.outerWidth() - 1,
6667 height: this.element.outerHeight() - 1,
6668 position: "absolute",
6669 left: this.elementOffset.left +"px",
6670 top: this.elementOffset.top +"px",
6671 zIndex: ++o.zIndex //TODO: Don't modify option
6672 });
6673
6674 this.helper
6675 .appendTo("body")
6676 .disableSelection();
6677
6678 } else {
6679 this.helper = this.element;
6680 }
6681
6682 },
6683
6684 _change: {
6685 e: function(event, dx) {
6686 return { width: this.originalSize.width + dx };
6687 },
6688 w: function(event, dx) {
6689 var cs = this.originalSize, sp = this.originalPosition;
6690 return { left: sp.left + dx, width: cs.width - dx };
6691 },
6692 n: function(event, dx, dy) {
6693 var cs = this.originalSize, sp = this.originalPosition;
6694 return { top: sp.top + dy, height: cs.height - dy };
6695 },
6696 s: function(event, dx, dy) {
6697 return { height: this.originalSize.height + dy };
6698 },
6699 se: function(event, dx, dy) {
6700 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
6701 },
6702 sw: function(event, dx, dy) {
6703 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
6704 },
6705 ne: function(event, dx, dy) {
6706 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
6707 },
6708 nw: function(event, dx, dy) {
6709 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
6710 }
6711 },
6712
6713 _propagate: function(n, event) {
6714 $.ui.plugin.call(this, n, [event, this.ui()]);
6715 (n !== "resize" && this._trigger(n, event, this.ui()));
6716 },
6717
6718 plugins: {},
6719
6720 ui: function() {
6721 return {
6722 originalElement: this.originalElement,
6723 element: this.element,
6724 helper: this.helper,
6725 position: this.position,
6726 size: this.size,
6727 originalSize: this.originalSize,
6728 originalPosition: this.originalPosition
6729 };
6730 }
6731
6732 });
6733
6734 /*
6735 * Resizable Extensions
6736 */
6737
6738 $.ui.plugin.add("resizable", "animate", {
6739
6740 stop: function( event ) {
6741 var that = $(this).data("ui-resizable"),
6742 o = that.options,
6743 pr = that._proportionallyResizeElements,
6744 ista = pr.length && (/textarea/i).test(pr[0].nodeName),
6745 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
6746 soffsetw = ista ? 0 : that.sizeDiff.width,
6747 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
6748 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
6749 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
6750
6751 that.element.animate(
6752 $.extend(style, top && left ? { top: top, left: left } : {}), {
6753 duration: o.animateDuration,
6754 easing: o.animateEasing,
6755 step: function() {
6756
6757 var data = {
6758 width: parseInt(that.element.css("width"), 10),
6759 height: parseInt(that.element.css("height"), 10),
6760 top: parseInt(that.element.css("top"), 10),
6761 left: parseInt(that.element.css("left"), 10)
6762 };
6763
6764 if (pr && pr.length) {
6765 $(pr[0]).css({ width: data.width, height: data.height });
6766 }
6767
6768 // propagating resize, and updating values for each animation step
6769 that._updateCache(data);
6770 that._propagate("resize", event);
6771
6772 }
6773 }
6774 );
6775 }
6776
6777 });
6778
6779 $.ui.plugin.add("resizable", "containment", {
6780
6781 start: function() {
6782 var element, p, co, ch, cw, width, height,
6783 that = $(this).data("ui-resizable"),
6784 o = that.options,
6785 el = that.element,
6786 oc = o.containment,
6787 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
6788
6789 if (!ce) {
6790 return;
6791 }
6792
6793 that.containerElement = $(ce);
6794
6795 if (/document/.test(oc) || oc === document) {
6796 that.containerOffset = { left: 0, top: 0 };
6797 that.containerPosition = { left: 0, top: 0 };
6798
6799 that.parentData = {
6800 element: $(document), left: 0, top: 0,
6801 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
6802 };
6803 }
6804
6805 // i'm a node, so compute top, left, right, bottom
6806 else {
6807 element = $(ce);
6808 p = [];
6809 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
6810
6811 that.containerOffset = element.offset();
6812 that.containerPosition = element.position();
6813 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
6814
6815 co = that.containerOffset;
6816 ch = that.containerSize.height;
6817 cw = that.containerSize.width;
6818 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
6819 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
6820
6821 that.parentData = {
6822 element: ce, left: co.left, top: co.top, width: width, height: height
6823 };
6824 }
6825 },
6826
6827 resize: function( event ) {
6828 var woset, hoset, isParent, isOffsetRelative,
6829 that = $(this).data("ui-resizable"),
6830 o = that.options,
6831 co = that.containerOffset, cp = that.position,
6832 pRatio = that._aspectRatio || event.shiftKey,
6833 cop = { top:0, left:0 }, ce = that.containerElement;
6834
6835 if (ce[0] !== document && (/static/).test(ce.css("position"))) {
6836 cop = co;
6837 }
6838
6839 if (cp.left < (that._helper ? co.left : 0)) {
6840 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
6841 if (pRatio) {
6842 that.size.height = that.size.width / that.aspectRatio;
6843 }
6844 that.position.left = o.helper ? co.left : 0;
6845 }
6846
6847 if (cp.top < (that._helper ? co.top : 0)) {
6848 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
6849 if (pRatio) {
6850 that.size.width = that.size.height * that.aspectRatio;
6851 }
6852 that.position.top = that._helper ? co.top : 0;
6853 }
6854
6855 that.offset.left = that.parentData.left+that.position.left;
6856 that.offset.top = that.parentData.top+that.position.top;
6857
6858 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
6859 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
6860
6861 isParent = that.containerElement.get(0) === that.element.parent().get(0);
6862 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
6863
6864 if(isParent && isOffsetRelative) {
6865 woset -= that.parentData.left;
6866 }
6867
6868 if (woset + that.size.width >= that.parentData.width) {
6869 that.size.width = that.parentData.width - woset;
6870 if (pRatio) {
6871 that.size.height = that.size.width / that.aspectRatio;
6872 }
6873 }
6874
6875 if (hoset + that.size.height >= that.parentData.height) {
6876 that.size.height = that.parentData.height - hoset;
6877 if (pRatio) {
6878 that.size.width = that.size.height * that.aspectRatio;
6879 }
6880 }
6881 },
6882
6883 stop: function(){
6884 var that = $(this).data("ui-resizable"),
6885 o = that.options,
6886 co = that.containerOffset,
6887 cop = that.containerPosition,
6888 ce = that.containerElement,
6889 helper = $(that.helper),
6890 ho = helper.offset(),
6891 w = helper.outerWidth() - that.sizeDiff.width,
6892 h = helper.outerHeight() - that.sizeDiff.height;
6893
6894 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
6895 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
6896 }
6897
6898 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
6899 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
6900 }
6901
6902 }
6903 });
6904
6905 $.ui.plugin.add("resizable", "alsoResize", {
6906
6907 start: function () {
6908 var that = $(this).data("ui-resizable"),
6909 o = that.options,
6910 _store = function (exp) {
6911 $(exp).each(function() {
6912 var el = $(this);
6913 el.data("ui-resizable-alsoresize", {
6914 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
6915 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
6916 });
6917 });
6918 };
6919
6920 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
6921 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
6922 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
6923 }else{
6924 _store(o.alsoResize);
6925 }
6926 },
6927
6928 resize: function (event, ui) {
6929 var that = $(this).data("ui-resizable"),
6930 o = that.options,
6931 os = that.originalSize,
6932 op = that.originalPosition,
6933 delta = {
6934 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
6935 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
6936 },
6937
6938 _alsoResize = function (exp, c) {
6939 $(exp).each(function() {
6940 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
6941 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
6942
6943 $.each(css, function (i, prop) {
6944 var sum = (start[prop]||0) + (delta[prop]||0);
6945 if (sum && sum >= 0) {
6946 style[prop] = sum || null;
6947 }
6948 });
6949
6950 el.css(style);
6951 });
6952 };
6953
6954 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
6955 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
6956 }else{
6957 _alsoResize(o.alsoResize);
6958 }
6959 },
6960
6961 stop: function () {
6962 $(this).removeData("resizable-alsoresize");
6963 }
6964 });
6965
6966 $.ui.plugin.add("resizable", "ghost", {
6967
6968 start: function() {
6969
6970 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
6971
6972 that.ghost = that.originalElement.clone();
6973 that.ghost
6974 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
6975 .addClass("ui-resizable-ghost")
6976 .addClass(typeof o.ghost === "string" ? o.ghost : "");
6977
6978 that.ghost.appendTo(that.helper);
6979
6980 },
6981
6982 resize: function(){
6983 var that = $(this).data("ui-resizable");
6984 if (that.ghost) {
6985 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
6986 }
6987 },
6988
6989 stop: function() {
6990 var that = $(this).data("ui-resizable");
6991 if (that.ghost && that.helper) {
6992 that.helper.get(0).removeChild(that.ghost.get(0));
6993 }
6994 }
6995
6996 });
6997
6998 $.ui.plugin.add("resizable", "grid", {
6999
7000 resize: function() {
7001 var that = $(this).data("ui-resizable"),
7002 o = that.options,
7003 cs = that.size,
7004 os = that.originalSize,
7005 op = that.originalPosition,
7006 a = that.axis,
7007 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
7008 gridX = (grid[0]||1),
7009 gridY = (grid[1]||1),
7010 ox = Math.round((cs.width - os.width) / gridX) * gridX,
7011 oy = Math.round((cs.height - os.height) / gridY) * gridY,
7012 newWidth = os.width + ox,
7013 newHeight = os.height + oy,
7014 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
7015 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
7016 isMinWidth = o.minWidth && (o.minWidth > newWidth),
7017 isMinHeight = o.minHeight && (o.minHeight > newHeight);
7018
7019 o.grid = grid;
7020
7021 if (isMinWidth) {
7022 newWidth = newWidth + gridX;
7023 }
7024 if (isMinHeight) {
7025 newHeight = newHeight + gridY;
7026 }
7027 if (isMaxWidth) {
7028 newWidth = newWidth - gridX;
7029 }
7030 if (isMaxHeight) {
7031 newHeight = newHeight - gridY;
7032 }
7033
7034 if (/^(se|s|e)$/.test(a)) {
7035 that.size.width = newWidth;
7036 that.size.height = newHeight;
7037 } else if (/^(ne)$/.test(a)) {
7038 that.size.width = newWidth;
7039 that.size.height = newHeight;
7040 that.position.top = op.top - oy;
7041 } else if (/^(sw)$/.test(a)) {
7042 that.size.width = newWidth;
7043 that.size.height = newHeight;
7044 that.position.left = op.left - ox;
7045 } else {
7046 that.size.width = newWidth;
7047 that.size.height = newHeight;
7048 that.position.top = op.top - oy;
7049 that.position.left = op.left - ox;
7050 }
7051 }
7052
7053 });
7054
7055 })(jQuery);
7056 (function( $, undefined ) {
7057
7058 $.widget("ui.selectable", $.ui.mouse, {
7059 version: "1.10.3",
7060 options: {
7061 appendTo: "body",
7062 autoRefresh: true,
7063 distance: 0,
7064 filter: "*",
7065 tolerance: "touch",
7066
7067 // callbacks
7068 selected: null,
7069 selecting: null,
7070 start: null,
7071 stop: null,
7072 unselected: null,
7073 unselecting: null
7074 },
7075 _create: function() {
7076 var selectees,
7077 that = this;
7078
7079 this.element.addClass("ui-selectable");
7080
7081 this.dragged = false;
7082
7083 // cache selectee children based on filter
7084 this.refresh = function() {
7085 selectees = $(that.options.filter, that.element[0]);
7086 selectees.addClass("ui-selectee");
7087 selectees.each(function() {
7088 var $this = $(this),
7089 pos = $this.offset();
7090 $.data(this, "selectable-item", {
7091 element: this,
7092 $element: $this,
7093 left: pos.left,
7094 top: pos.top,
7095 right: pos.left + $this.outerWidth(),
7096 bottom: pos.top + $this.outerHeight(),
7097 startselected: false,
7098 selected: $this.hasClass("ui-selected"),
7099 selecting: $this.hasClass("ui-selecting"),
7100 unselecting: $this.hasClass("ui-unselecting")
7101 });
7102 });
7103 };
7104 this.refresh();
7105
7106 this.selectees = selectees.addClass("ui-selectee");
7107
7108 this._mouseInit();
7109
7110 this.helper = $("<div class='ui-selectable-helper'></div>");
7111 },
7112
7113 _destroy: function() {
7114 this.selectees
7115 .removeClass("ui-selectee")
7116 .removeData("selectable-item");
7117 this.element
7118 .removeClass("ui-selectable ui-selectable-disabled");
7119 this._mouseDestroy();
7120 },
7121
7122 _mouseStart: function(event) {
7123 var that = this,
7124 options = this.options;
7125
7126 this.opos = [event.pageX, event.pageY];
7127
7128 if (this.options.disabled) {
7129 return;
7130 }
7131
7132 this.selectees = $(options.filter, this.element[0]);
7133
7134 this._trigger("start", event);
7135
7136 $(options.appendTo).append(this.helper);
7137 // position helper (lasso)
7138 this.helper.css({
7139 "left": event.pageX,
7140 "top": event.pageY,
7141 "width": 0,
7142 "height": 0
7143 });
7144
7145 if (options.autoRefresh) {
7146 this.refresh();
7147 }
7148
7149 this.selectees.filter(".ui-selected").each(function() {
7150 var selectee = $.data(this, "selectable-item");
7151 selectee.startselected = true;
7152 if (!event.metaKey && !event.ctrlKey) {
7153 selectee.$element.removeClass("ui-selected");
7154 selectee.selected = false;
7155 selectee.$element.addClass("ui-unselecting");
7156 selectee.unselecting = true;
7157 // selectable UNSELECTING callback
7158 that._trigger("unselecting", event, {
7159 unselecting: selectee.element
7160 });
7161 }
7162 });
7163
7164 $(event.target).parents().addBack().each(function() {
7165 var doSelect,
7166 selectee = $.data(this, "selectable-item");
7167 if (selectee) {
7168 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
7169 selectee.$element
7170 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
7171 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
7172 selectee.unselecting = !doSelect;
7173 selectee.selecting = doSelect;
7174 selectee.selected = doSelect;
7175 // selectable (UN)SELECTING callback
7176 if (doSelect) {
7177 that._trigger("selecting", event, {
7178 selecting: selectee.element
7179 });
7180 } else {
7181 that._trigger("unselecting", event, {
7182 unselecting: selectee.element
7183 });
7184 }
7185 return false;
7186 }
7187 });
7188
7189 },
7190
7191 _mouseDrag: function(event) {
7192
7193 this.dragged = true;
7194
7195 if (this.options.disabled) {
7196 return;
7197 }
7198
7199 var tmp,
7200 that = this,
7201 options = this.options,
7202 x1 = this.opos[0],
7203 y1 = this.opos[1],
7204 x2 = event.pageX,
7205 y2 = event.pageY;
7206
7207 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
7208 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
7209 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
7210
7211 this.selectees.each(function() {
7212 var selectee = $.data(this, "selectable-item"),
7213 hit = false;
7214
7215 //prevent helper from being selected if appendTo: selectable
7216 if (!selectee || selectee.element === that.element[0]) {
7217 return;
7218 }
7219
7220 if (options.tolerance === "touch") {
7221 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
7222 } else if (options.tolerance === "fit") {
7223 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
7224 }
7225
7226 if (hit) {
7227 // SELECT
7228 if (selectee.selected) {
7229 selectee.$element.removeClass("ui-selected");
7230 selectee.selected = false;
7231 }
7232 if (selectee.unselecting) {
7233 selectee.$element.removeClass("ui-unselecting");
7234 selectee.unselecting = false;
7235 }
7236 if (!selectee.selecting) {
7237 selectee.$element.addClass("ui-selecting");
7238 selectee.selecting = true;
7239 // selectable SELECTING callback
7240 that._trigger("selecting", event, {
7241 selecting: selectee.element
7242 });
7243 }
7244 } else {
7245 // UNSELECT
7246 if (selectee.selecting) {
7247 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
7248 selectee.$element.removeClass("ui-selecting");
7249 selectee.selecting = false;
7250 selectee.$element.addClass("ui-selected");
7251 selectee.selected = true;
7252 } else {
7253 selectee.$element.removeClass("ui-selecting");
7254 selectee.selecting = false;
7255 if (selectee.startselected) {
7256 selectee.$element.addClass("ui-unselecting");
7257 selectee.unselecting = true;
7258 }
7259 // selectable UNSELECTING callback
7260 that._trigger("unselecting", event, {
7261 unselecting: selectee.element
7262 });
7263 }
7264 }
7265 if (selectee.selected) {
7266 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
7267 selectee.$element.removeClass("ui-selected");
7268 selectee.selected = false;
7269
7270 selectee.$element.addClass("ui-unselecting");
7271 selectee.unselecting = true;
7272 // selectable UNSELECTING callback
7273 that._trigger("unselecting", event, {
7274 unselecting: selectee.element
7275 });
7276 }
7277 }
7278 }
7279 });
7280
7281 return false;
7282 },
7283
7284 _mouseStop: function(event) {
7285 var that = this;
7286
7287 this.dragged = false;
7288
7289 $(".ui-unselecting", this.element[0]).each(function() {
7290 var selectee = $.data(this, "selectable-item");
7291 selectee.$element.removeClass("ui-unselecting");
7292 selectee.unselecting = false;
7293 selectee.startselected = false;
7294 that._trigger("unselected", event, {
7295 unselected: selectee.element
7296 });
7297 });
7298 $(".ui-selecting", this.element[0]).each(function() {
7299 var selectee = $.data(this, "selectable-item");
7300 selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
7301 selectee.selecting = false;
7302 selectee.selected = true;
7303 selectee.startselected = true;
7304 that._trigger("selected", event, {
7305 selected: selectee.element
7306 });
7307 });
7308 this._trigger("stop", event);
7309
7310 this.helper.remove();
7311
7312 return false;
7313 }
7314
7315 });
7316
7317 })(jQuery);
7318 (function( $, undefined ) {
7319
7320 /*jshint loopfunc: true */
7321
7322 function isOverAxis( x, reference, size ) {
7323 return ( x > reference ) && ( x < ( reference + size ) );
7324 }
7325
7326 function isFloating(item) {
7327 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
7328 }
7329
7330 $.widget("ui.sortable", $.ui.mouse, {
7331 version: "1.10.3",
7332 widgetEventPrefix: "sort",
7333 ready: false,
7334 options: {
7335 appendTo: "parent",
7336 axis: false,
7337 connectWith: false,
7338 containment: false,
7339 cursor: "auto",
7340 cursorAt: false,
7341 dropOnEmpty: true,
7342 forcePlaceholderSize: false,
7343 forceHelperSize: false,
7344 grid: false,
7345 handle: false,
7346 helper: "original",
7347 items: "> *",
7348 opacity: false,
7349 placeholder: false,
7350 revert: false,
7351 scroll: true,
7352 scrollSensitivity: 20,
7353 scrollSpeed: 20,
7354 scope: "default",
7355 tolerance: "intersect",
7356 zIndex: 1000,
7357
7358 // callbacks
7359 activate: null,
7360 beforeStop: null,
7361 change: null,
7362 deactivate: null,
7363 out: null,
7364 over: null,
7365 receive: null,
7366 remove: null,
7367 sort: null,
7368 start: null,
7369 stop: null,
7370 update: null
7371 },
7372 _create: function() {
7373
7374 var o = this.options;
7375 this.containerCache = {};
7376 this.element.addClass("ui-sortable");
7377
7378 //Get the items
7379 this.refresh();
7380
7381 //Let's determine if the items are being displayed horizontally
7382 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
7383
7384 //Let's determine the parent's offset
7385 this.offset = this.element.offset();
7386
7387 //Initialize mouse events for interaction
7388 this._mouseInit();
7389
7390 //We're ready to go
7391 this.ready = true;
7392
7393 },
7394
7395 _destroy: function() {
7396 this.element
7397 .removeClass("ui-sortable ui-sortable-disabled");
7398 this._mouseDestroy();
7399
7400 for ( var i = this.items.length - 1; i >= 0; i-- ) {
7401 this.items[i].item.removeData(this.widgetName + "-item");
7402 }
7403
7404 return this;
7405 },
7406
7407 _setOption: function(key, value){
7408 if ( key === "disabled" ) {
7409 this.options[ key ] = value;
7410
7411 this.widget().toggleClass( "ui-sortable-disabled", !!value );
7412 } else {
7413 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
7414 $.Widget.prototype._setOption.apply(this, arguments);
7415 }
7416 },
7417
7418 _mouseCapture: function(event, overrideHandle) {
7419 var currentItem = null,
7420 validHandle = false,
7421 that = this;
7422
7423 if (this.reverting) {
7424 return false;
7425 }
7426
7427 if(this.options.disabled || this.options.type === "static") {
7428 return false;
7429 }
7430
7431 //We have to refresh the items data once first
7432 this._refreshItems(event);
7433
7434 //Find out if the clicked node (or one of its parents) is a actual item in this.items
7435 $(event.target).parents().each(function() {
7436 if($.data(this, that.widgetName + "-item") === that) {
7437 currentItem = $(this);
7438 return false;
7439 }
7440 });
7441 if($.data(event.target, that.widgetName + "-item") === that) {
7442 currentItem = $(event.target);
7443 }
7444
7445 if(!currentItem) {
7446 return false;
7447 }
7448 if(this.options.handle && !overrideHandle) {
7449 $(this.options.handle, currentItem).find("*").addBack().each(function() {
7450 if(this === event.target) {
7451 validHandle = true;
7452 }
7453 });
7454 if(!validHandle) {
7455 return false;
7456 }
7457 }
7458
7459 this.currentItem = currentItem;
7460 this._removeCurrentsFromItems();
7461 return true;
7462
7463 },
7464
7465 _mouseStart: function(event, overrideHandle, noActivation) {
7466
7467 var i, body,
7468 o = this.options;
7469
7470 this.currentContainer = this;
7471
7472 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
7473 this.refreshPositions();
7474
7475 //Create and append the visible helper
7476 this.helper = this._createHelper(event);
7477
7478 //Cache the helper size
7479 this._cacheHelperProportions();
7480
7481 /*
7482 * - Position generation -
7483 * This block generates everything position related - it's the core of draggables.
7484 */
7485
7486 //Cache the margins of the original element
7487 this._cacheMargins();
7488
7489 //Get the next scrolling parent
7490 this.scrollParent = this.helper.scrollParent();
7491
7492 //The element's absolute position on the page minus margins
7493 this.offset = this.currentItem.offset();
7494 this.offset = {
7495 top: this.offset.top - this.margins.top,
7496 left: this.offset.left - this.margins.left
7497 };
7498
7499 $.extend(this.offset, {
7500 click: { //Where the click happened, relative to the element
7501 left: event.pageX - this.offset.left,
7502 top: event.pageY - this.offset.top
7503 },
7504 parent: this._getParentOffset(),
7505 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
7506 });
7507
7508 // Only after we got the offset, we can change the helper's position to absolute
7509 // TODO: Still need to figure out a way to make relative sorting possible
7510 this.helper.css("position", "absolute");
7511 this.cssPosition = this.helper.css("position");
7512
7513 //Generate the original position
7514 this.originalPosition = this._generatePosition(event);
7515 this.originalPageX = event.pageX;
7516 this.originalPageY = event.pageY;
7517
7518 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
7519 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
7520
7521 //Cache the former DOM position
7522 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
7523
7524 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
7525 if(this.helper[0] !== this.currentItem[0]) {
7526 this.currentItem.hide();
7527 }
7528
7529 //Create the placeholder
7530 this._createPlaceholder();
7531
7532 //Set a containment if given in the options
7533 if(o.containment) {
7534 this._setContainment();
7535 }
7536
7537 if( o.cursor && o.cursor !== "auto" ) { // cursor option
7538 body = this.document.find( "body" );
7539
7540 // support: IE
7541 this.storedCursor = body.css( "cursor" );
7542 body.css( "cursor", o.cursor );
7543
7544 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
7545 }
7546
7547 if(o.opacity) { // opacity option
7548 if (this.helper.css("opacity")) {
7549 this._storedOpacity = this.helper.css("opacity");
7550 }
7551 this.helper.css("opacity", o.opacity);
7552 }
7553
7554 if(o.zIndex) { // zIndex option
7555 if (this.helper.css("zIndex")) {
7556 this._storedZIndex = this.helper.css("zIndex");
7557 }
7558 this.helper.css("zIndex", o.zIndex);
7559 }
7560
7561 //Prepare scrolling
7562 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
7563 this.overflowOffset = this.scrollParent.offset();
7564 }
7565
7566 //Call callbacks
7567 this._trigger("start", event, this._uiHash());
7568
7569 //Recache the helper size
7570 if(!this._preserveHelperProportions) {
7571 this._cacheHelperProportions();
7572 }
7573
7574
7575 //Post "activate" events to possible containers
7576 if( !noActivation ) {
7577 for ( i = this.containers.length - 1; i >= 0; i-- ) {
7578 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
7579 }
7580 }
7581
7582 //Prepare possible droppables
7583 if($.ui.ddmanager) {
7584 $.ui.ddmanager.current = this;
7585 }
7586
7587 if ($.ui.ddmanager && !o.dropBehaviour) {
7588 $.ui.ddmanager.prepareOffsets(this, event);
7589 }
7590
7591 this.dragging = true;
7592
7593 this.helper.addClass("ui-sortable-helper");
7594 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
7595 return true;
7596
7597 },
7598
7599 _mouseDrag: function(event) {
7600 var i, item, itemElement, intersection,
7601 o = this.options,
7602 scrolled = false;
7603
7604 //Compute the helpers position
7605 this.position = this._generatePosition(event);
7606 this.positionAbs = this._convertPositionTo("absolute");
7607
7608 if (!this.lastPositionAbs) {
7609 this.lastPositionAbs = this.positionAbs;
7610 }
7611
7612 //Do scrolling
7613 if(this.options.scroll) {
7614 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
7615
7616 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
7617 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
7618 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
7619 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
7620 }
7621
7622 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
7623 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
7624 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
7625 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
7626 }
7627
7628 } else {
7629
7630 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
7631 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
7632 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
7633 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
7634 }
7635
7636 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
7637 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
7638 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
7639 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
7640 }
7641
7642 }
7643
7644 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
7645 $.ui.ddmanager.prepareOffsets(this, event);
7646 }
7647 }
7648
7649 //Regenerate the absolute position used for position checks
7650 this.positionAbs = this._convertPositionTo("absolute");
7651
7652 //Set the helper position
7653 if(!this.options.axis || this.options.axis !== "y") {
7654 this.helper[0].style.left = this.position.left+"px";
7655 }
7656 if(!this.options.axis || this.options.axis !== "x") {
7657 this.helper[0].style.top = this.position.top+"px";
7658 }
7659
7660 //Rearrange
7661 for (i = this.items.length - 1; i >= 0; i--) {
7662
7663 //Cache variables and intersection, continue if no intersection
7664 item = this.items[i];
7665 itemElement = item.item[0];
7666 intersection = this._intersectsWithPointer(item);
7667 if (!intersection) {
7668 continue;
7669 }
7670
7671 // Only put the placeholder inside the current Container, skip all
7672 // items form other containers. This works because when moving
7673 // an item from one container to another the
7674 // currentContainer is switched before the placeholder is moved.
7675 //
7676 // Without this moving items in "sub-sortables" can cause the placeholder to jitter
7677 // beetween the outer and inner container.
7678 if (item.instance !== this.currentContainer) {
7679 continue;
7680 }
7681
7682 // cannot intersect with itself
7683 // no useless actions that have been done before
7684 // no action if the item moved is the parent of the item checked
7685 if (itemElement !== this.currentItem[0] &&
7686 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
7687 !$.contains(this.placeholder[0], itemElement) &&
7688 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
7689 ) {
7690
7691 this.direction = intersection === 1 ? "down" : "up";
7692
7693 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
7694 this._rearrange(event, item);
7695 } else {
7696 break;
7697 }
7698
7699 this._trigger("change", event, this._uiHash());
7700 break;
7701 }
7702 }
7703
7704 //Post events to containers
7705 this._contactContainers(event);
7706
7707 //Interconnect with droppables
7708 if($.ui.ddmanager) {
7709 $.ui.ddmanager.drag(this, event);
7710 }
7711
7712 //Call callbacks
7713 this._trigger("sort", event, this._uiHash());
7714
7715 this.lastPositionAbs = this.positionAbs;
7716 return false;
7717
7718 },
7719
7720 _mouseStop: function(event, noPropagation) {
7721
7722 if(!event) {
7723 return;
7724 }
7725
7726 //If we are using droppables, inform the manager about the drop
7727 if ($.ui.ddmanager && !this.options.dropBehaviour) {
7728 $.ui.ddmanager.drop(this, event);
7729 }
7730
7731 if(this.options.revert) {
7732 var that = this,
7733 cur = this.placeholder.offset(),
7734 axis = this.options.axis,
7735 animation = {};
7736
7737 if ( !axis || axis === "x" ) {
7738 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
7739 }
7740 if ( !axis || axis === "y" ) {
7741 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
7742 }
7743 this.reverting = true;
7744 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
7745 that._clear(event);
7746 });
7747 } else {
7748 this._clear(event, noPropagation);
7749 }
7750
7751 return false;
7752
7753 },
7754
7755 cancel: function() {
7756
7757 if(this.dragging) {
7758
7759 this._mouseUp({ target: null });
7760
7761 if(this.options.helper === "original") {
7762 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
7763 } else {
7764 this.currentItem.show();
7765 }
7766
7767 //Post deactivating events to containers
7768 for (var i = this.containers.length - 1; i >= 0; i--){
7769 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
7770 if(this.containers[i].containerCache.over) {
7771 this.containers[i]._trigger("out", null, this._uiHash(this));
7772 this.containers[i].containerCache.over = 0;
7773 }
7774 }
7775
7776 }
7777
7778 if (this.placeholder) {
7779 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
7780 if(this.placeholder[0].parentNode) {
7781 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
7782 }
7783 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
7784 this.helper.remove();
7785 }
7786
7787 $.extend(this, {
7788 helper: null,
7789 dragging: false,
7790 reverting: false,
7791 _noFinalSort: null
7792 });
7793
7794 if(this.domPosition.prev) {
7795 $(this.domPosition.prev).after(this.currentItem);
7796 } else {
7797 $(this.domPosition.parent).prepend(this.currentItem);
7798 }
7799 }
7800
7801 return this;
7802
7803 },
7804
7805 serialize: function(o) {
7806
7807 var items = this._getItemsAsjQuery(o && o.connected),
7808 str = [];
7809 o = o || {};
7810
7811 $(items).each(function() {
7812 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
7813 if (res) {
7814 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
7815 }
7816 });
7817
7818 if(!str.length && o.key) {
7819 str.push(o.key + "=");
7820 }
7821
7822 return str.join("&");
7823
7824 },
7825
7826 toArray: function(o) {
7827
7828 var items = this._getItemsAsjQuery(o && o.connected),
7829 ret = [];
7830
7831 o = o || {};
7832
7833 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
7834 return ret;
7835
7836 },
7837
7838 /* Be careful with the following core functions */
7839 _intersectsWith: function(item) {
7840
7841 var x1 = this.positionAbs.left,
7842 x2 = x1 + this.helperProportions.width,
7843 y1 = this.positionAbs.top,
7844 y2 = y1 + this.helperProportions.height,
7845 l = item.left,
7846 r = l + item.width,
7847 t = item.top,
7848 b = t + item.height,
7849 dyClick = this.offset.click.top,
7850 dxClick = this.offset.click.left,
7851 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
7852 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
7853 isOverElement = isOverElementHeight && isOverElementWidth;
7854
7855 if ( this.options.tolerance === "pointer" ||
7856 this.options.forcePointerForContainers ||
7857 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
7858 ) {
7859 return isOverElement;
7860 } else {
7861
7862 return (l < x1 + (this.helperProportions.width / 2) && // Right Half
7863 x2 - (this.helperProportions.width / 2) < r && // Left Half
7864 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
7865 y2 - (this.helperProportions.height / 2) < b ); // Top Half
7866
7867 }
7868 },
7869
7870 _intersectsWithPointer: function(item) {
7871
7872 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
7873 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
7874 isOverElement = isOverElementHeight && isOverElementWidth,
7875 verticalDirection = this._getDragVerticalDirection(),
7876 horizontalDirection = this._getDragHorizontalDirection();
7877
7878 if (!isOverElement) {
7879 return false;
7880 }
7881
7882 return this.floating ?
7883 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
7884 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
7885
7886 },
7887
7888 _intersectsWithSides: function(item) {
7889
7890 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
7891 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
7892 verticalDirection = this._getDragVerticalDirection(),
7893 horizontalDirection = this._getDragHorizontalDirection();
7894
7895 if (this.floating && horizontalDirection) {
7896 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
7897 } else {
7898 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
7899 }
7900
7901 },
7902
7903 _getDragVerticalDirection: function() {
7904 var delta = this.positionAbs.top - this.lastPositionAbs.top;
7905 return delta !== 0 && (delta > 0 ? "down" : "up");
7906 },
7907
7908 _getDragHorizontalDirection: function() {
7909 var delta = this.positionAbs.left - this.lastPositionAbs.left;
7910 return delta !== 0 && (delta > 0 ? "right" : "left");
7911 },
7912
7913 refresh: function(event) {
7914 this._refreshItems(event);
7915 this.refreshPositions();
7916 return this;
7917 },
7918
7919 _connectWith: function() {
7920 var options = this.options;
7921 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
7922 },
7923
7924 _getItemsAsjQuery: function(connected) {
7925
7926 var i, j, cur, inst,
7927 items = [],
7928 queries = [],
7929 connectWith = this._connectWith();
7930
7931 if(connectWith && connected) {
7932 for (i = connectWith.length - 1; i >= 0; i--){
7933 cur = $(connectWith[i]);
7934 for ( j = cur.length - 1; j >= 0; j--){
7935 inst = $.data(cur[j], this.widgetFullName);
7936 if(inst && inst !== this && !inst.options.disabled) {
7937 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
7938 }
7939 }
7940 }
7941 }
7942
7943 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
7944
7945 for (i = queries.length - 1; i >= 0; i--){
7946 queries[i][0].each(function() {
7947 items.push(this);
7948 });
7949 }
7950
7951 return $(items);
7952
7953 },
7954
7955 _removeCurrentsFromItems: function() {
7956
7957 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
7958
7959 this.items = $.grep(this.items, function (item) {
7960 for (var j=0; j < list.length; j++) {
7961 if(list[j] === item.item[0]) {
7962 return false;
7963 }
7964 }
7965 return true;
7966 });
7967
7968 },
7969
7970 _refreshItems: function(event) {
7971
7972 this.items = [];
7973 this.containers = [this];
7974
7975 var i, j, cur, inst, targetData, _queries, item, queriesLength,
7976 items = this.items,
7977 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
7978 connectWith = this._connectWith();
7979
7980 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
7981 for (i = connectWith.length - 1; i >= 0; i--){
7982 cur = $(connectWith[i]);
7983 for (j = cur.length - 1; j >= 0; j--){
7984 inst = $.data(cur[j], this.widgetFullName);
7985 if(inst && inst !== this && !inst.options.disabled) {
7986 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
7987 this.containers.push(inst);
7988 }
7989 }
7990 }
7991 }
7992
7993 for (i = queries.length - 1; i >= 0; i--) {
7994 targetData = queries[i][1];
7995 _queries = queries[i][0];
7996
7997 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
7998 item = $(_queries[j]);
7999
8000 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
8001
8002 items.push({
8003 item: item,
8004 instance: targetData,
8005 width: 0, height: 0,
8006 left: 0, top: 0
8007 });
8008 }
8009 }
8010
8011 },
8012
8013 refreshPositions: function(fast) {
8014
8015 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
8016 if(this.offsetParent && this.helper) {
8017 this.offset.parent = this._getParentOffset();
8018 }
8019
8020 var i, item, t, p;
8021
8022 for (i = this.items.length - 1; i >= 0; i--){
8023 item = this.items[i];
8024
8025 //We ignore calculating positions of all connected containers when we're not over them
8026 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
8027 continue;
8028 }
8029
8030 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
8031
8032 if (!fast) {
8033 item.width = t.outerWidth();
8034 item.height = t.outerHeight();
8035 }
8036
8037 p = t.offset();
8038 item.left = p.left;
8039 item.top = p.top;
8040 }
8041
8042 if(this.options.custom && this.options.custom.refreshContainers) {
8043 this.options.custom.refreshContainers.call(this);
8044 } else {
8045 for (i = this.containers.length - 1; i >= 0; i--){
8046 p = this.containers[i].element.offset();
8047 this.containers[i].containerCache.left = p.left;
8048 this.containers[i].containerCache.top = p.top;
8049 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
8050 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
8051 }
8052 }
8053
8054 return this;
8055 },
8056
8057 _createPlaceholder: function(that) {
8058 that = that || this;
8059 var className,
8060 o = that.options;
8061
8062 if(!o.placeholder || o.placeholder.constructor === String) {
8063 className = o.placeholder;
8064 o.placeholder = {
8065 element: function() {
8066
8067 var nodeName = that.currentItem[0].nodeName.toLowerCase(),
8068 element = $( "<" + nodeName + ">", that.document[0] )
8069 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
8070 .removeClass("ui-sortable-helper");
8071
8072 if ( nodeName === "tr" ) {
8073 that.currentItem.children().each(function() {
8074 $( "<td>&#160;</td>", that.document[0] )
8075 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
8076 .appendTo( element );
8077 });
8078 } else if ( nodeName === "img" ) {
8079 element.attr( "src", that.currentItem.attr( "src" ) );
8080 }
8081
8082 if ( !className ) {
8083 element.css( "visibility", "hidden" );
8084 }
8085
8086 return element;
8087 },
8088 update: function(container, p) {
8089
8090 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
8091 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
8092 if(className && !o.forcePlaceholderSize) {
8093 return;
8094 }
8095
8096 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
8097 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
8098 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
8099 }
8100 };
8101 }
8102
8103 //Create the placeholder
8104 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
8105
8106 //Append it after the actual current item
8107 that.currentItem.after(that.placeholder);
8108
8109 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
8110 o.placeholder.update(that, that.placeholder);
8111
8112 },
8113
8114 _contactContainers: function(event) {
8115 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
8116 innermostContainer = null,
8117 innermostIndex = null;
8118
8119 // get innermost container that intersects with item
8120 for (i = this.containers.length - 1; i >= 0; i--) {
8121
8122 // never consider a container that's located within the item itself
8123 if($.contains(this.currentItem[0], this.containers[i].element[0])) {
8124 continue;
8125 }
8126
8127 if(this._intersectsWith(this.containers[i].containerCache)) {
8128
8129 // if we've already found a container and it's more "inner" than this, then continue
8130 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
8131 continue;
8132 }
8133
8134 innermostContainer = this.containers[i];
8135 innermostIndex = i;
8136
8137 } else {
8138 // container doesn't intersect. trigger "out" event if necessary
8139 if(this.containers[i].containerCache.over) {
8140 this.containers[i]._trigger("out", event, this._uiHash(this));
8141 this.containers[i].containerCache.over = 0;
8142 }
8143 }
8144
8145 }
8146
8147 // if no intersecting containers found, return
8148 if(!innermostContainer) {
8149 return;
8150 }
8151
8152 // move the item into the container if it's not there already
8153 if(this.containers.length === 1) {
8154 if (!this.containers[innermostIndex].containerCache.over) {
8155 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
8156 this.containers[innermostIndex].containerCache.over = 1;
8157 }
8158 } else {
8159
8160 //When entering a new container, we will find the item with the least distance and append our item near it
8161 dist = 10000;
8162 itemWithLeastDistance = null;
8163 floating = innermostContainer.floating || isFloating(this.currentItem);
8164 posProperty = floating ? "left" : "top";
8165 sizeProperty = floating ? "width" : "height";
8166 base = this.positionAbs[posProperty] + this.offset.click[posProperty];
8167 for (j = this.items.length - 1; j >= 0; j--) {
8168 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
8169 continue;
8170 }
8171 if(this.items[j].item[0] === this.currentItem[0]) {
8172 continue;
8173 }
8174 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
8175 continue;
8176 }
8177 cur = this.items[j].item.offset()[posProperty];
8178 nearBottom = false;
8179 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
8180 nearBottom = true;
8181 cur += this.items[j][sizeProperty];
8182 }
8183
8184 if(Math.abs(cur - base) < dist) {
8185 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
8186 this.direction = nearBottom ? "up": "down";
8187 }
8188 }
8189
8190 //Check if dropOnEmpty is enabled
8191 if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
8192 return;
8193 }
8194
8195 if(this.currentContainer === this.containers[innermostIndex]) {
8196 return;
8197 }
8198
8199 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
8200 this._trigger("change", event, this._uiHash());
8201 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
8202 this.currentContainer = this.containers[innermostIndex];
8203
8204 //Update the placeholder
8205 this.options.placeholder.update(this.currentContainer, this.placeholder);
8206
8207 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
8208 this.containers[innermostIndex].containerCache.over = 1;
8209 }
8210
8211
8212 },
8213
8214 _createHelper: function(event) {
8215
8216 var o = this.options,
8217 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
8218
8219 //Add the helper to the DOM if that didn't happen already
8220 if(!helper.parents("body").length) {
8221 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
8222 }
8223
8224 if(helper[0] === this.currentItem[0]) {
8225 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
8226 }
8227
8228 if(!helper[0].style.width || o.forceHelperSize) {
8229 helper.width(this.currentItem.width());
8230 }
8231 if(!helper[0].style.height || o.forceHelperSize) {
8232 helper.height(this.currentItem.height());
8233 }
8234
8235 return helper;
8236
8237 },
8238
8239 _adjustOffsetFromHelper: function(obj) {
8240 if (typeof obj === "string") {
8241 obj = obj.split(" ");
8242 }
8243 if ($.isArray(obj)) {
8244 obj = {left: +obj[0], top: +obj[1] || 0};
8245 }
8246 if ("left" in obj) {
8247 this.offset.click.left = obj.left + this.margins.left;
8248 }
8249 if ("right" in obj) {
8250 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
8251 }
8252 if ("top" in obj) {
8253 this.offset.click.top = obj.top + this.margins.top;
8254 }
8255 if ("bottom" in obj) {
8256 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
8257 }
8258 },
8259
8260 _getParentOffset: function() {
8261
8262
8263 //Get the offsetParent and cache its position
8264 this.offsetParent = this.helper.offsetParent();
8265 var po = this.offsetParent.offset();
8266
8267 // This is a special case where we need to modify a offset calculated on start, since the following happened:
8268 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
8269 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
8270 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
8271 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
8272 po.left += this.scrollParent.scrollLeft();
8273 po.top += this.scrollParent.scrollTop();
8274 }
8275
8276 // This needs to be actually done for all browsers, since pageX/pageY includes this information
8277 // with an ugly IE fix
8278 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
8279 po = { top: 0, left: 0 };
8280 }
8281
8282 return {
8283 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
8284 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
8285 };
8286
8287 },
8288
8289 _getRelativeOffset: function() {
8290
8291 if(this.cssPosition === "relative") {
8292 var p = this.currentItem.position();
8293 return {
8294 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
8295 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
8296 };
8297 } else {
8298 return { top: 0, left: 0 };
8299 }
8300
8301 },
8302
8303 _cacheMargins: function() {
8304 this.margins = {
8305 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
8306 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
8307 };
8308 },
8309
8310 _cacheHelperProportions: function() {
8311 this.helperProportions = {
8312 width: this.helper.outerWidth(),
8313 height: this.helper.outerHeight()
8314 };
8315 },
8316
8317 _setContainment: function() {
8318
8319 var ce, co, over,
8320 o = this.options;
8321 if(o.containment === "parent") {
8322 o.containment = this.helper[0].parentNode;
8323 }
8324 if(o.containment === "document" || o.containment === "window") {
8325 this.containment = [
8326 0 - this.offset.relative.left - this.offset.parent.left,
8327 0 - this.offset.relative.top - this.offset.parent.top,
8328 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
8329 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
8330 ];
8331 }
8332
8333 if(!(/^(document|window|parent)$/).test(o.containment)) {
8334 ce = $(o.containment)[0];
8335 co = $(o.containment).offset();
8336 over = ($(ce).css("overflow") !== "hidden");
8337
8338 this.containment = [
8339 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
8340 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
8341 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
8342 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
8343 ];
8344 }
8345
8346 },
8347
8348 _convertPositionTo: function(d, pos) {
8349
8350 if(!pos) {
8351 pos = this.position;
8352 }
8353 var mod = d === "absolute" ? 1 : -1,
8354 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
8355 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
8356
8357 return {
8358 top: (
8359 pos.top + // The absolute mouse position
8360 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
8361 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
8362 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
8363 ),
8364 left: (
8365 pos.left + // The absolute mouse position
8366 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
8367 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
8368 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
8369 )
8370 };
8371
8372 },
8373
8374 _generatePosition: function(event) {
8375
8376 var top, left,
8377 o = this.options,
8378 pageX = event.pageX,
8379 pageY = event.pageY,
8380 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
8381
8382 // This is another very weird special case that only happens for relative elements:
8383 // 1. If the css position is relative
8384 // 2. and the scroll parent is the document or similar to the offset parent
8385 // we have to refresh the relative offset during the scroll so there are no jumps
8386 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
8387 this.offset.relative = this._getRelativeOffset();
8388 }
8389
8390 /*
8391 * - Position constraining -
8392 * Constrain the position to a mix of grid, containment.
8393 */
8394
8395 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
8396
8397 if(this.containment) {
8398 if(event.pageX - this.offset.click.left < this.containment[0]) {
8399 pageX = this.containment[0] + this.offset.click.left;
8400 }
8401 if(event.pageY - this.offset.click.top < this.containment[1]) {
8402 pageY = this.containment[1] + this.offset.click.top;
8403 }
8404 if(event.pageX - this.offset.click.left > this.containment[2]) {
8405 pageX = this.containment[2] + this.offset.click.left;
8406 }
8407 if(event.pageY - this.offset.click.top > this.containment[3]) {
8408 pageY = this.containment[3] + this.offset.click.top;
8409 }
8410 }
8411
8412 if(o.grid) {
8413 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
8414 pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
8415
8416 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
8417 pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
8418 }
8419
8420 }
8421
8422 return {
8423 top: (
8424 pageY - // The absolute mouse position
8425 this.offset.click.top - // Click offset (relative to the element)
8426 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
8427 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
8428 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
8429 ),
8430 left: (
8431 pageX - // The absolute mouse position
8432 this.offset.click.left - // Click offset (relative to the element)
8433 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
8434 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
8435 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
8436 )
8437 };
8438
8439 },
8440
8441 _rearrange: function(event, i, a, hardRefresh) {
8442
8443 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
8444
8445 //Various things done here to improve the performance:
8446 // 1. we create a setTimeout, that calls refreshPositions
8447 // 2. on the instance, we have a counter variable, that get's higher after every append
8448 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
8449 // 4. this lets only the last addition to the timeout stack through
8450 this.counter = this.counter ? ++this.counter : 1;
8451 var counter = this.counter;
8452
8453 this._delay(function() {
8454 if(counter === this.counter) {
8455 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
8456 }
8457 });
8458
8459 },
8460
8461 _clear: function(event, noPropagation) {
8462
8463 this.reverting = false;
8464 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
8465 // everything else normalized again
8466 var i,
8467 delayedTriggers = [];
8468
8469 // We first have to update the dom position of the actual currentItem
8470 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
8471 if(!this._noFinalSort && this.currentItem.parent().length) {
8472 this.placeholder.before(this.currentItem);
8473 }
8474 this._noFinalSort = null;
8475
8476 if(this.helper[0] === this.currentItem[0]) {
8477 for(i in this._storedCSS) {
8478 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
8479 this._storedCSS[i] = "";
8480 }
8481 }
8482 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
8483 } else {
8484 this.currentItem.show();
8485 }
8486
8487 if(this.fromOutside && !noPropagation) {
8488 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
8489 }
8490 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
8491 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
8492 }
8493
8494 // Check if the items Container has Changed and trigger appropriate
8495 // events.
8496 if (this !== this.currentContainer) {
8497 if(!noPropagation) {
8498 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
8499 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
8500 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
8501 }
8502 }
8503
8504
8505 //Post events to containers
8506 for (i = this.containers.length - 1; i >= 0; i--){
8507 if(!noPropagation) {
8508 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
8509 }
8510 if(this.containers[i].containerCache.over) {
8511 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
8512 this.containers[i].containerCache.over = 0;
8513 }
8514 }
8515
8516 //Do what was originally in plugins
8517 if ( this.storedCursor ) {
8518 this.document.find( "body" ).css( "cursor", this.storedCursor );
8519 this.storedStylesheet.remove();
8520 }
8521 if(this._storedOpacity) {
8522 this.helper.css("opacity", this._storedOpacity);
8523 }
8524 if(this._storedZIndex) {
8525 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
8526 }
8527
8528 this.dragging = false;
8529 if(this.cancelHelperRemoval) {
8530 if(!noPropagation) {
8531 this._trigger("beforeStop", event, this._uiHash());
8532 for (i=0; i < delayedTriggers.length; i++) {
8533 delayedTriggers[i].call(this, event);
8534 } //Trigger all delayed events
8535 this._trigger("stop", event, this._uiHash());
8536 }
8537
8538 this.fromOutside = false;
8539 return false;
8540 }
8541
8542 if(!noPropagation) {
8543 this._trigger("beforeStop", event, this._uiHash());
8544 }
8545
8546 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
8547 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
8548
8549 if(this.helper[0] !== this.currentItem[0]) {
8550 this.helper.remove();
8551 }
8552 this.helper = null;
8553
8554 if(!noPropagation) {
8555 for (i=0; i < delayedTriggers.length; i++) {
8556 delayedTriggers[i].call(this, event);
8557 } //Trigger all delayed events
8558 this._trigger("stop", event, this._uiHash());
8559 }
8560
8561 this.fromOutside = false;
8562 return true;
8563
8564 },
8565
8566 _trigger: function() {
8567 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
8568 this.cancel();
8569 }
8570 },
8571
8572 _uiHash: function(_inst) {
8573 var inst = _inst || this;
8574 return {
8575 helper: inst.helper,
8576 placeholder: inst.placeholder || $([]),
8577 position: inst.position,
8578 originalPosition: inst.originalPosition,
8579 offset: inst.positionAbs,
8580 item: inst.currentItem,
8581 sender: _inst ? _inst.element : null
8582 };
8583 }
8584
8585 });
8586
8587 })(jQuery);
8588 (function( $, undefined ) {
8589
8590 var uid = 0,
8591 hideProps = {},
8592 showProps = {};
8593
8594 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
8595 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
8596 showProps.height = showProps.paddingTop = showProps.paddingBottom =
8597 showProps.borderTopWidth = showProps.borderBottomWidth = "show";
8598
8599 $.widget( "ui.accordion", {
8600 version: "1.10.3",
8601 options: {
8602 active: 0,
8603 animate: {},
8604 collapsible: false,
8605 event: "click",
8606 header: "> li > :first-child,> :not(li):even",
8607 heightStyle: "auto",
8608 icons: {
8609 activeHeader: "ui-icon-triangle-1-s",
8610 header: "ui-icon-triangle-1-e"
8611 },
8612
8613 // callbacks
8614 activate: null,
8615 beforeActivate: null
8616 },
8617
8618 _create: function() {
8619 var options = this.options;
8620 this.prevShow = this.prevHide = $();
8621 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
8622 // ARIA
8623 .attr( "role", "tablist" );
8624
8625 // don't allow collapsible: false and active: false / null
8626 if ( !options.collapsible && (options.active === false || options.active == null) ) {
8627 options.active = 0;
8628 }
8629
8630 this._processPanels();
8631 // handle negative values
8632 if ( options.active < 0 ) {
8633 options.active += this.headers.length;
8634 }
8635 this._refresh();
8636 },
8637
8638 _getCreateEventData: function() {
8639 return {
8640 header: this.active,
8641 panel: !this.active.length ? $() : this.active.next(),
8642 content: !this.active.length ? $() : this.active.next()
8643 };
8644 },
8645
8646 _createIcons: function() {
8647 var icons = this.options.icons;
8648 if ( icons ) {
8649 $( "<span>" )
8650 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
8651 .prependTo( this.headers );
8652 this.active.children( ".ui-accordion-header-icon" )
8653 .removeClass( icons.header )
8654 .addClass( icons.activeHeader );
8655 this.headers.addClass( "ui-accordion-icons" );
8656 }
8657 },
8658
8659 _destroyIcons: function() {
8660 this.headers
8661 .removeClass( "ui-accordion-icons" )
8662 .children( ".ui-accordion-header-icon" )
8663 .remove();
8664 },
8665
8666 _destroy: function() {
8667 var contents;
8668
8669 // clean up main element
8670 this.element
8671 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
8672 .removeAttr( "role" );
8673
8674 // clean up headers
8675 this.headers
8676 .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
8677 .removeAttr( "role" )
8678 .removeAttr( "aria-selected" )
8679 .removeAttr( "aria-controls" )
8680 .removeAttr( "tabIndex" )
8681 .each(function() {
8682 if ( /^ui-accordion/.test( this.id ) ) {
8683 this.removeAttribute( "id" );
8684 }
8685 });
8686 this._destroyIcons();
8687
8688 // clean up content panels
8689 contents = this.headers.next()
8690 .css( "display", "" )
8691 .removeAttr( "role" )
8692 .removeAttr( "aria-expanded" )
8693 .removeAttr( "aria-hidden" )
8694 .removeAttr( "aria-labelledby" )
8695 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
8696 .each(function() {
8697 if ( /^ui-accordion/.test( this.id ) ) {
8698 this.removeAttribute( "id" );
8699 }
8700 });
8701 if ( this.options.heightStyle !== "content" ) {
8702 contents.css( "height", "" );
8703 }
8704 },
8705
8706 _setOption: function( key, value ) {
8707 if ( key === "active" ) {
8708 // _activate() will handle invalid values and update this.options
8709 this._activate( value );
8710 return;
8711 }
8712
8713 if ( key === "event" ) {
8714 if ( this.options.event ) {
8715 this._off( this.headers, this.options.event );
8716 }
8717 this._setupEvents( value );
8718 }
8719
8720 this._super( key, value );
8721
8722 // setting collapsible: false while collapsed; open first panel
8723 if ( key === "collapsible" && !value && this.options.active === false ) {
8724 this._activate( 0 );
8725 }
8726
8727 if ( key === "icons" ) {
8728 this._destroyIcons();
8729 if ( value ) {
8730 this._createIcons();
8731 }
8732 }
8733
8734 // #5332 - opacity doesn't cascade to positioned elements in IE
8735 // so we need to add the disabled class to the headers and panels
8736 if ( key === "disabled" ) {
8737 this.headers.add( this.headers.next() )
8738 .toggleClass( "ui-state-disabled", !!value );
8739 }
8740 },
8741
8742 _keydown: function( event ) {
8743 /*jshint maxcomplexity:15*/
8744 if ( event.altKey || event.ctrlKey ) {
8745 return;
8746 }
8747
8748 var keyCode = $.ui.keyCode,
8749 length = this.headers.length,
8750 currentIndex = this.headers.index( event.target ),
8751 toFocus = false;
8752
8753 switch ( event.keyCode ) {
8754 case keyCode.RIGHT:
8755 case keyCode.DOWN:
8756 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
8757 break;
8758 case keyCode.LEFT:
8759 case keyCode.UP:
8760 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
8761 break;
8762 case keyCode.SPACE:
8763 case keyCode.ENTER:
8764 this._eventHandler( event );
8765 break;
8766 case keyCode.HOME:
8767 toFocus = this.headers[ 0 ];
8768 break;
8769 case keyCode.END:
8770 toFocus = this.headers[ length - 1 ];
8771 break;
8772 }
8773
8774 if ( toFocus ) {
8775 $( event.target ).attr( "tabIndex", -1 );
8776 $( toFocus ).attr( "tabIndex", 0 );
8777 toFocus.focus();
8778 event.preventDefault();
8779 }
8780 },
8781
8782 _panelKeyDown : function( event ) {
8783 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
8784 $( event.currentTarget ).prev().focus();
8785 }
8786 },
8787
8788 refresh: function() {
8789 var options = this.options;
8790 this._processPanels();
8791
8792 // was collapsed or no panel
8793 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
8794 options.active = false;
8795 this.active = $();
8796 // active false only when collapsible is true
8797 } else if ( options.active === false ) {
8798 this._activate( 0 );
8799 // was active, but active panel is gone
8800 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
8801 // all remaining panel are disabled
8802 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
8803 options.active = false;
8804 this.active = $();
8805 // activate previous panel
8806 } else {
8807 this._activate( Math.max( 0, options.active - 1 ) );
8808 }
8809 // was active, active panel still exists
8810 } else {
8811 // make sure active index is correct
8812 options.active = this.headers.index( this.active );
8813 }
8814
8815 this._destroyIcons();
8816
8817 this._refresh();
8818 },
8819
8820 _processPanels: function() {
8821 this.headers = this.element.find( this.options.header )
8822 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
8823
8824 this.headers.next()
8825 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
8826 .filter(":not(.ui-accordion-content-active)")
8827 .hide();
8828 },
8829
8830 _refresh: function() {
8831 var maxHeight,
8832 options = this.options,
8833 heightStyle = options.heightStyle,
8834 parent = this.element.parent(),
8835 accordionId = this.accordionId = "ui-accordion-" +
8836 (this.element.attr( "id" ) || ++uid);
8837
8838 this.active = this._findActive( options.active )
8839 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
8840 .removeClass( "ui-corner-all" );
8841 this.active.next()
8842 .addClass( "ui-accordion-content-active" )
8843 .show();
8844
8845 this.headers
8846 .attr( "role", "tab" )
8847 .each(function( i ) {
8848 var header = $( this ),
8849 headerId = header.attr( "id" ),
8850 panel = header.next(),
8851 panelId = panel.attr( "id" );
8852 if ( !headerId ) {
8853 headerId = accordionId + "-header-" + i;
8854 header.attr( "id", headerId );
8855 }
8856 if ( !panelId ) {
8857 panelId = accordionId + "-panel-" + i;
8858 panel.attr( "id", panelId );
8859 }
8860 header.attr( "aria-controls", panelId );
8861 panel.attr( "aria-labelledby", headerId );
8862 })
8863 .next()
8864 .attr( "role", "tabpanel" );
8865
8866 this.headers
8867 .not( this.active )
8868 .attr({
8869 "aria-selected": "false",
8870 tabIndex: -1
8871 })
8872 .next()
8873 .attr({
8874 "aria-expanded": "false",
8875 "aria-hidden": "true"
8876 })
8877 .hide();
8878
8879 // make sure at least one header is in the tab order
8880 if ( !this.active.length ) {
8881 this.headers.eq( 0 ).attr( "tabIndex", 0 );
8882 } else {
8883 this.active.attr({
8884 "aria-selected": "true",
8885 tabIndex: 0
8886 })
8887 .next()
8888 .attr({
8889 "aria-expanded": "true",
8890 "aria-hidden": "false"
8891 });
8892 }
8893
8894 this._createIcons();
8895
8896 this._setupEvents( options.event );
8897
8898 if ( heightStyle === "fill" ) {
8899 maxHeight = parent.height();
8900 this.element.siblings( ":visible" ).each(function() {
8901 var elem = $( this ),
8902 position = elem.css( "position" );
8903
8904 if ( position === "absolute" || position === "fixed" ) {
8905 return;
8906 }
8907 maxHeight -= elem.outerHeight( true );
8908 });
8909
8910 this.headers.each(function() {
8911 maxHeight -= $( this ).outerHeight( true );
8912 });
8913
8914 this.headers.next()
8915 .each(function() {
8916 $( this ).height( Math.max( 0, maxHeight -
8917 $( this ).innerHeight() + $( this ).height() ) );
8918 })
8919 .css( "overflow", "auto" );
8920 } else if ( heightStyle === "auto" ) {
8921 maxHeight = 0;
8922 this.headers.next()
8923 .each(function() {
8924 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
8925 })
8926 .height( maxHeight );
8927 }
8928 },
8929
8930 _activate: function( index ) {
8931 var active = this._findActive( index )[ 0 ];
8932
8933 // trying to activate the already active panel
8934 if ( active === this.active[ 0 ] ) {
8935 return;
8936 }
8937
8938 // trying to collapse, simulate a click on the currently active header
8939 active = active || this.active[ 0 ];
8940
8941 this._eventHandler({
8942 target: active,
8943 currentTarget: active,
8944 preventDefault: $.noop
8945 });
8946 },
8947
8948 _findActive: function( selector ) {
8949 return typeof selector === "number" ? this.headers.eq( selector ) : $();
8950 },
8951
8952 _setupEvents: function( event ) {
8953 var events = {
8954 keydown: "_keydown"
8955 };
8956 if ( event ) {
8957 $.each( event.split(" "), function( index, eventName ) {
8958 events[ eventName ] = "_eventHandler";
8959 });
8960 }
8961
8962 this._off( this.headers.add( this.headers.next() ) );
8963 this._on( this.headers, events );
8964 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
8965 this._hoverable( this.headers );
8966 this._focusable( this.headers );
8967 },
8968
8969 _eventHandler: function( event ) {
8970 var options = this.options,
8971 active = this.active,
8972 clicked = $( event.currentTarget ),
8973 clickedIsActive = clicked[ 0 ] === active[ 0 ],
8974 collapsing = clickedIsActive && options.collapsible,
8975 toShow = collapsing ? $() : clicked.next(),
8976 toHide = active.next(),
8977 eventData = {
8978 oldHeader: active,
8979 oldPanel: toHide,
8980 newHeader: collapsing ? $() : clicked,
8981 newPanel: toShow
8982 };
8983
8984 event.preventDefault();
8985
8986 if (
8987 // click on active header, but not collapsible
8988 ( clickedIsActive && !options.collapsible ) ||
8989 // allow canceling activation
8990 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
8991 return;
8992 }
8993
8994 options.active = collapsing ? false : this.headers.index( clicked );
8995
8996 // when the call to ._toggle() comes after the class changes
8997 // it causes a very odd bug in IE 8 (see #6720)
8998 this.active = clickedIsActive ? $() : clicked;
8999 this._toggle( eventData );
9000
9001 // switch classes
9002 // corner classes on the previously active header stay after the animation
9003 active.removeClass( "ui-accordion-header-active ui-state-active" );
9004 if ( options.icons ) {
9005 active.children( ".ui-accordion-header-icon" )
9006 .removeClass( options.icons.activeHeader )
9007 .addClass( options.icons.header );
9008 }
9009
9010 if ( !clickedIsActive ) {
9011 clicked
9012 .removeClass( "ui-corner-all" )
9013 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
9014 if ( options.icons ) {
9015 clicked.children( ".ui-accordion-header-icon" )
9016 .removeClass( options.icons.header )
9017 .addClass( options.icons.activeHeader );
9018 }
9019
9020 clicked
9021 .next()
9022 .addClass( "ui-accordion-content-active" );
9023 }
9024 },
9025
9026 _toggle: function( data ) {
9027 var toShow = data.newPanel,
9028 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
9029
9030 // handle activating a panel during the animation for another activation
9031 this.prevShow.add( this.prevHide ).stop( true, true );
9032 this.prevShow = toShow;
9033 this.prevHide = toHide;
9034
9035 if ( this.options.animate ) {
9036 this._animate( toShow, toHide, data );
9037 } else {
9038 toHide.hide();
9039 toShow.show();
9040 this._toggleComplete( data );
9041 }
9042
9043 toHide.attr({
9044 "aria-expanded": "false",
9045 "aria-hidden": "true"
9046 });
9047 toHide.prev().attr( "aria-selected", "false" );
9048 // if we're switching panels, remove the old header from the tab order
9049 // if we're opening from collapsed state, remove the previous header from the tab order
9050 // if we're collapsing, then keep the collapsing header in the tab order
9051 if ( toShow.length && toHide.length ) {
9052 toHide.prev().attr( "tabIndex", -1 );
9053 } else if ( toShow.length ) {
9054 this.headers.filter(function() {
9055 return $( this ).attr( "tabIndex" ) === 0;
9056 })
9057 .attr( "tabIndex", -1 );
9058 }
9059
9060 toShow
9061 .attr({
9062 "aria-expanded": "true",
9063 "aria-hidden": "false"
9064 })
9065 .prev()
9066 .attr({
9067 "aria-selected": "true",
9068 tabIndex: 0
9069 });
9070 },
9071
9072 _animate: function( toShow, toHide, data ) {
9073 var total, easing, duration,
9074 that = this,
9075 adjust = 0,
9076 down = toShow.length &&
9077 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
9078 animate = this.options.animate || {},
9079 options = down && animate.down || animate,
9080 complete = function() {
9081 that._toggleComplete( data );
9082 };
9083
9084 if ( typeof options === "number" ) {
9085 duration = options;
9086 }
9087 if ( typeof options === "string" ) {
9088 easing = options;
9089 }
9090 // fall back from options to animation in case of partial down settings
9091 easing = easing || options.easing || animate.easing;
9092 duration = duration || options.duration || animate.duration;
9093
9094 if ( !toHide.length ) {
9095 return toShow.animate( showProps, duration, easing, complete );
9096 }
9097 if ( !toShow.length ) {
9098 return toHide.animate( hideProps, duration, easing, complete );
9099 }
9100
9101 total = toShow.show().outerHeight();
9102 toHide.animate( hideProps, {
9103 duration: duration,
9104 easing: easing,
9105 step: function( now, fx ) {
9106 fx.now = Math.round( now );
9107 }
9108 });
9109 toShow
9110 .hide()
9111 .animate( showProps, {
9112 duration: duration,
9113 easing: easing,
9114 complete: complete,
9115 step: function( now, fx ) {
9116 fx.now = Math.round( now );
9117 if ( fx.prop !== "height" ) {
9118 adjust += fx.now;
9119 } else if ( that.options.heightStyle !== "content" ) {
9120 fx.now = Math.round( total - toHide.outerHeight() - adjust );
9121 adjust = 0;
9122 }
9123 }
9124 });
9125 },
9126
9127 _toggleComplete: function( data ) {
9128 var toHide = data.oldPanel;
9129
9130 toHide
9131 .removeClass( "ui-accordion-content-active" )
9132 .prev()
9133 .removeClass( "ui-corner-top" )
9134 .addClass( "ui-corner-all" );
9135
9136 // Work around for rendering bug in IE (#5421)
9137 if ( toHide.length ) {
9138 toHide.parent()[0].className = toHide.parent()[0].className;
9139 }
9140
9141 this._trigger( "activate", null, data );
9142 }
9143 });
9144
9145 })( jQuery );
9146 (function( $, undefined ) {
9147
9148 // used to prevent race conditions with remote data sources
9149 var requestIndex = 0;
9150
9151 $.widget( "ui.autocomplete", {
9152 version: "1.10.3",
9153 defaultElement: "<input>",
9154 options: {
9155 appendTo: null,
9156 autoFocus: false,
9157 delay: 300,
9158 minLength: 1,
9159 position: {
9160 my: "left top",
9161 at: "left bottom",
9162 collision: "none"
9163 },
9164 source: null,
9165
9166 // callbacks
9167 change: null,
9168 close: null,
9169 focus: null,
9170 open: null,
9171 response: null,
9172 search: null,
9173 select: null
9174 },
9175
9176 pending: 0,
9177
9178 _create: function() {
9179 // Some browsers only repeat keydown events, not keypress events,
9180 // so we use the suppressKeyPress flag to determine if we've already
9181 // handled the keydown event. #7269
9182 // Unfortunately the code for & in keypress is the same as the up arrow,
9183 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
9184 // events when we know the keydown event was used to modify the
9185 // search term. #7799
9186 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
9187 nodeName = this.element[0].nodeName.toLowerCase(),
9188 isTextarea = nodeName === "textarea",
9189 isInput = nodeName === "input";
9190
9191 this.isMultiLine =
9192 // Textareas are always multi-line
9193 isTextarea ? true :
9194 // Inputs are always single-line, even if inside a contentEditable element
9195 // IE also treats inputs as contentEditable
9196 isInput ? false :
9197 // All other element types are determined by whether or not they're contentEditable
9198 this.element.prop( "isContentEditable" );
9199
9200 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
9201 this.isNewMenu = true;
9202
9203 this.element
9204 .addClass( "ui-autocomplete-input" )
9205 .attr( "autocomplete", "off" );
9206
9207 this._on( this.element, {
9208 keydown: function( event ) {
9209 /*jshint maxcomplexity:15*/
9210 if ( this.element.prop( "readOnly" ) ) {
9211 suppressKeyPress = true;
9212 suppressInput = true;
9213 suppressKeyPressRepeat = true;
9214 return;
9215 }
9216
9217 suppressKeyPress = false;
9218 suppressInput = false;
9219 suppressKeyPressRepeat = false;
9220 var keyCode = $.ui.keyCode;
9221 switch( event.keyCode ) {
9222 case keyCode.PAGE_UP:
9223 suppressKeyPress = true;
9224 this._move( "previousPage", event );
9225 break;
9226 case keyCode.PAGE_DOWN:
9227 suppressKeyPress = true;
9228 this._move( "nextPage", event );
9229 break;
9230 case keyCode.UP:
9231 suppressKeyPress = true;
9232 this._keyEvent( "previous", event );
9233 break;
9234 case keyCode.DOWN:
9235 suppressKeyPress = true;
9236 this._keyEvent( "next", event );
9237 break;
9238 case keyCode.ENTER:
9239 case keyCode.NUMPAD_ENTER:
9240 // when menu is open and has focus
9241 if ( this.menu.active ) {
9242 // #6055 - Opera still allows the keypress to occur
9243 // which causes forms to submit
9244 suppressKeyPress = true;
9245 event.preventDefault();
9246 this.menu.select( event );
9247 }
9248 break;
9249 case keyCode.TAB:
9250 if ( this.menu.active ) {
9251 this.menu.select( event );
9252 }
9253 break;
9254 case keyCode.ESCAPE:
9255 if ( this.menu.element.is( ":visible" ) ) {
9256 this._value( this.term );
9257 this.close( event );
9258 // Different browsers have different default behavior for escape
9259 // Single press can mean undo or clear
9260 // Double press in IE means clear the whole form
9261 event.preventDefault();
9262 }
9263 break;
9264 default:
9265 suppressKeyPressRepeat = true;
9266 // search timeout should be triggered before the input value is changed
9267 this._searchTimeout( event );
9268 break;
9269 }
9270 },
9271 keypress: function( event ) {
9272 if ( suppressKeyPress ) {
9273 suppressKeyPress = false;
9274 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
9275 event.preventDefault();
9276 }
9277 return;
9278 }
9279 if ( suppressKeyPressRepeat ) {
9280 return;
9281 }
9282
9283 // replicate some key handlers to allow them to repeat in Firefox and Opera
9284 var keyCode = $.ui.keyCode;
9285 switch( event.keyCode ) {
9286 case keyCode.PAGE_UP:
9287 this._move( "previousPage", event );
9288 break;
9289 case keyCode.PAGE_DOWN:
9290 this._move( "nextPage", event );
9291 break;
9292 case keyCode.UP:
9293 this._keyEvent( "previous", event );
9294 break;
9295 case keyCode.DOWN:
9296 this._keyEvent( "next", event );
9297 break;
9298 }
9299 },
9300 input: function( event ) {
9301 if ( suppressInput ) {
9302 suppressInput = false;
9303 event.preventDefault();
9304 return;
9305 }
9306 this._searchTimeout( event );
9307 },
9308 focus: function() {
9309 this.selectedItem = null;
9310 this.previous = this._value();
9311 },
9312 blur: function( event ) {
9313 if ( this.cancelBlur ) {
9314 delete this.cancelBlur;
9315 return;
9316 }
9317
9318 clearTimeout( this.searching );
9319 this.close( event );
9320 this._change( event );
9321 }
9322 });
9323
9324 this._initSource();
9325 this.menu = $( "<ul>" )
9326 .addClass( "ui-autocomplete ui-front" )
9327 .appendTo( this._appendTo() )
9328 .menu({
9329 // disable ARIA support, the live region takes care of that
9330 role: null
9331 })
9332 .hide()
9333 .data( "ui-menu" );
9334
9335 this._on( this.menu.element, {
9336 mousedown: function( event ) {
9337 // prevent moving focus out of the text field
9338 event.preventDefault();
9339
9340 // IE doesn't prevent moving focus even with event.preventDefault()
9341 // so we set a flag to know when we should ignore the blur event
9342 this.cancelBlur = true;
9343 this._delay(function() {
9344 delete this.cancelBlur;
9345 });
9346
9347 // clicking on the scrollbar causes focus to shift to the body
9348 // but we can't detect a mouseup or a click immediately afterward
9349 // so we have to track the next mousedown and close the menu if
9350 // the user clicks somewhere outside of the autocomplete
9351 var menuElement = this.menu.element[ 0 ];
9352 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
9353 this._delay(function() {
9354 var that = this;
9355 this.document.one( "mousedown", function( event ) {
9356 if ( event.target !== that.element[ 0 ] &&
9357 event.target !== menuElement &&
9358 !$.contains( menuElement, event.target ) ) {
9359 that.close();
9360 }
9361 });
9362 });
9363 }
9364 },
9365 menufocus: function( event, ui ) {
9366 // support: Firefox
9367 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
9368 if ( this.isNewMenu ) {
9369 this.isNewMenu = false;
9370 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
9371 this.menu.blur();
9372
9373 this.document.one( "mousemove", function() {
9374 $( event.target ).trigger( event.originalEvent );
9375 });
9376
9377 return;
9378 }
9379 }
9380
9381 var item = ui.item.data( "ui-autocomplete-item" );
9382 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
9383 // use value to match what will end up in the input, if it was a key event
9384 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
9385 this._value( item.value );
9386 }
9387 } else {
9388 // Normally the input is populated with the item's value as the
9389 // menu is navigated, causing screen readers to notice a change and
9390 // announce the item. Since the focus event was canceled, this doesn't
9391 // happen, so we update the live region so that screen readers can
9392 // still notice the change and announce it.
9393 this.liveRegion.text( item.value );
9394 }
9395 },
9396 menuselect: function( event, ui ) {
9397 var item = ui.item.data( "ui-autocomplete-item" ),
9398 previous = this.previous;
9399
9400 // only trigger when focus was lost (click on menu)
9401 if ( this.element[0] !== this.document[0].activeElement ) {
9402 this.element.focus();
9403 this.previous = previous;
9404 // #6109 - IE triggers two focus events and the second
9405 // is asynchronous, so we need to reset the previous
9406 // term synchronously and asynchronously :-(
9407 this._delay(function() {
9408 this.previous = previous;
9409 this.selectedItem = item;
9410 });
9411 }
9412
9413 if ( false !== this._trigger( "select", event, { item: item } ) ) {
9414 this._value( item.value );
9415 }
9416 // reset the term after the select event
9417 // this allows custom select handling to work properly
9418 this.term = this._value();
9419
9420 this.close( event );
9421 this.selectedItem = item;
9422 }
9423 });
9424
9425 this.liveRegion = $( "<span>", {
9426 role: "status",
9427 "aria-live": "polite"
9428 })
9429 .addClass( "ui-helper-hidden-accessible" )
9430 .insertBefore( this.element );
9431
9432 // turning off autocomplete prevents the browser from remembering the
9433 // value when navigating through history, so we re-enable autocomplete
9434 // if the page is unloaded before the widget is destroyed. #7790
9435 this._on( this.window, {
9436 beforeunload: function() {
9437 this.element.removeAttr( "autocomplete" );
9438 }
9439 });
9440 },
9441
9442 _destroy: function() {
9443 clearTimeout( this.searching );
9444 this.element
9445 .removeClass( "ui-autocomplete-input" )
9446 .removeAttr( "autocomplete" );
9447 this.menu.element.remove();
9448 this.liveRegion.remove();
9449 },
9450
9451 _setOption: function( key, value ) {
9452 this._super( key, value );
9453 if ( key === "source" ) {
9454 this._initSource();
9455 }
9456 if ( key === "appendTo" ) {
9457 this.menu.element.appendTo( this._appendTo() );
9458 }
9459 if ( key === "disabled" && value && this.xhr ) {
9460 this.xhr.abort();
9461 }
9462 },
9463
9464 _appendTo: function() {
9465 var element = this.options.appendTo;
9466
9467 if ( element ) {
9468 element = element.jquery || element.nodeType ?
9469 $( element ) :
9470 this.document.find( element ).eq( 0 );
9471 }
9472
9473 if ( !element ) {
9474 element = this.element.closest( ".ui-front" );
9475 }
9476
9477 if ( !element.length ) {
9478 element = this.document[0].body;
9479 }
9480
9481 return element;
9482 },
9483
9484 _initSource: function() {
9485 var array, url,
9486 that = this;
9487 if ( $.isArray(this.options.source) ) {
9488 array = this.options.source;
9489 this.source = function( request, response ) {
9490 response( $.ui.autocomplete.filter( array, request.term ) );
9491 };
9492 } else if ( typeof this.options.source === "string" ) {
9493 url = this.options.source;
9494 this.source = function( request, response ) {
9495 if ( that.xhr ) {
9496 that.xhr.abort();
9497 }
9498 that.xhr = $.ajax({
9499 url: url,
9500 data: request,
9501 dataType: "json",
9502 success: function( data ) {
9503 response( data );
9504 },
9505 error: function() {
9506 response( [] );
9507 }
9508 });
9509 };
9510 } else {
9511 this.source = this.options.source;
9512 }
9513 },
9514
9515 _searchTimeout: function( event ) {
9516 clearTimeout( this.searching );
9517 this.searching = this._delay(function() {
9518 // only search if the value has changed
9519 if ( this.term !== this._value() ) {
9520 this.selectedItem = null;
9521 this.search( null, event );
9522 }
9523 }, this.options.delay );
9524 },
9525
9526 search: function( value, event ) {
9527 value = value != null ? value : this._value();
9528
9529 // always save the actual value, not the one passed as an argument
9530 this.term = this._value();
9531
9532 if ( value.length < this.options.minLength ) {
9533 return this.close( event );
9534 }
9535
9536 if ( this._trigger( "search", event ) === false ) {
9537 return;
9538 }
9539
9540 return this._search( value );
9541 },
9542
9543 _search: function( value ) {
9544 this.pending++;
9545 this.element.addClass( "ui-autocomplete-loading" );
9546 this.cancelSearch = false;
9547
9548 this.source( { term: value }, this._response() );
9549 },
9550
9551 _response: function() {
9552 var that = this,
9553 index = ++requestIndex;
9554
9555 return function( content ) {
9556 if ( index === requestIndex ) {
9557 that.__response( content );
9558 }
9559
9560 that.pending--;
9561 if ( !that.pending ) {
9562 that.element.removeClass( "ui-autocomplete-loading" );
9563 }
9564 };
9565 },
9566
9567 __response: function( content ) {
9568 if ( content ) {
9569 content = this._normalize( content );
9570 }
9571 this._trigger( "response", null, { content: content } );
9572 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
9573 this._suggest( content );
9574 this._trigger( "open" );
9575 } else {
9576 // use ._close() instead of .close() so we don't cancel future searches
9577 this._close();
9578 }
9579 },
9580
9581 close: function( event ) {
9582 this.cancelSearch = true;
9583 this._close( event );
9584 },
9585
9586 _close: function( event ) {
9587 if ( this.menu.element.is( ":visible" ) ) {
9588 this.menu.element.hide();
9589 this.menu.blur();
9590 this.isNewMenu = true;
9591 this._trigger( "close", event );
9592 }
9593 },
9594
9595 _change: function( event ) {
9596 if ( this.previous !== this._value() ) {
9597 this._trigger( "change", event, { item: this.selectedItem } );
9598 }
9599 },
9600
9601 _normalize: function( items ) {
9602 // assume all items have the right format when the first item is complete
9603 if ( items.length && items[0].label && items[0].value ) {
9604 return items;
9605 }
9606 return $.map( items, function( item ) {
9607 if ( typeof item === "string" ) {
9608 return {
9609 label: item,
9610 value: item
9611 };
9612 }
9613 return $.extend({
9614 label: item.label || item.value,
9615 value: item.value || item.label
9616 }, item );
9617 });
9618 },
9619
9620 _suggest: function( items ) {
9621 var ul = this.menu.element.empty();
9622 this._renderMenu( ul, items );
9623 this.isNewMenu = true;
9624 this.menu.refresh();
9625
9626 // size and position menu
9627 ul.show();
9628 this._resizeMenu();
9629 ul.position( $.extend({
9630 of: this.element
9631 }, this.options.position ));
9632
9633 if ( this.options.autoFocus ) {
9634 this.menu.next();
9635 }
9636 },
9637
9638 _resizeMenu: function() {
9639 var ul = this.menu.element;
9640 ul.outerWidth( Math.max(
9641 // Firefox wraps long text (possibly a rounding bug)
9642 // so we add 1px to avoid the wrapping (#7513)
9643 ul.width( "" ).outerWidth() + 1,
9644 this.element.outerWidth()
9645 ) );
9646 },
9647
9648 _renderMenu: function( ul, items ) {
9649 var that = this;
9650 $.each( items, function( index, item ) {
9651 that._renderItemData( ul, item );
9652 });
9653 },
9654
9655 _renderItemData: function( ul, item ) {
9656 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
9657 },
9658
9659 _renderItem: function( ul, item ) {
9660 return $( "<li>" )
9661 .append( $( "<a>" ).text( item.label ) )
9662 .appendTo( ul );
9663 },
9664
9665 _move: function( direction, event ) {
9666 if ( !this.menu.element.is( ":visible" ) ) {
9667 this.search( null, event );
9668 return;
9669 }
9670 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
9671 this.menu.isLastItem() && /^next/.test( direction ) ) {
9672 this._value( this.term );
9673 this.menu.blur();
9674 return;
9675 }
9676 this.menu[ direction ]( event );
9677 },
9678
9679 widget: function() {
9680 return this.menu.element;
9681 },
9682
9683 _value: function() {
9684 return this.valueMethod.apply( this.element, arguments );
9685 },
9686
9687 _keyEvent: function( keyEvent, event ) {
9688 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
9689 this._move( keyEvent, event );
9690
9691 // prevents moving cursor to beginning/end of the text field in some browsers
9692 event.preventDefault();
9693 }
9694 }
9695 });
9696
9697 $.extend( $.ui.autocomplete, {
9698 escapeRegex: function( value ) {
9699 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
9700 },
9701 filter: function(array, term) {
9702 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
9703 return $.grep( array, function(value) {
9704 return matcher.test( value.label || value.value || value );
9705 });
9706 }
9707 });
9708
9709
9710 // live region extension, adding a `messages` option
9711 // NOTE: This is an experimental API. We are still investigating
9712 // a full solution for string manipulation and internationalization.
9713 $.widget( "ui.autocomplete", $.ui.autocomplete, {
9714 options: {
9715 messages: {
9716 noResults: "No search results.",
9717 results: function( amount ) {
9718 return amount + ( amount > 1 ? " results are" : " result is" ) +
9719 " available, use up and down arrow keys to navigate.";
9720 }
9721 }
9722 },
9723
9724 __response: function( content ) {
9725 var message;
9726 this._superApply( arguments );
9727 if ( this.options.disabled || this.cancelSearch ) {
9728 return;
9729 }
9730 if ( content && content.length ) {
9731 message = this.options.messages.results( content.length );
9732 } else {
9733 message = this.options.messages.noResults;
9734 }
9735 this.liveRegion.text( message );
9736 }
9737 });
9738
9739 }( jQuery ));
9740 (function( $, undefined ) {
9741
9742 var lastActive, startXPos, startYPos, clickDragged,
9743 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
9744 stateClasses = "ui-state-hover ui-state-active ",
9745 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
9746 formResetHandler = function() {
9747 var form = $( this );
9748 setTimeout(function() {
9749 form.find( ":ui-button" ).button( "refresh" );
9750 }, 1 );
9751 },
9752 radioGroup = function( radio ) {
9753 var name = radio.name,
9754 form = radio.form,
9755 radios = $( [] );
9756 if ( name ) {
9757 name = name.replace( /'/g, "\\'" );
9758 if ( form ) {
9759 radios = $( form ).find( "[name='" + name + "']" );
9760 } else {
9761 radios = $( "[name='" + name + "']", radio.ownerDocument )
9762 .filter(function() {
9763 return !this.form;
9764 });
9765 }
9766 }
9767 return radios;
9768 };
9769
9770 $.widget( "ui.button", {
9771 version: "1.10.3",
9772 defaultElement: "<button>",
9773 options: {
9774 disabled: null,
9775 text: true,
9776 label: null,
9777 icons: {
9778 primary: null,
9779 secondary: null
9780 }
9781 },
9782 _create: function() {
9783 this.element.closest( "form" )
9784 .unbind( "reset" + this.eventNamespace )
9785 .bind( "reset" + this.eventNamespace, formResetHandler );
9786
9787 if ( typeof this.options.disabled !== "boolean" ) {
9788 this.options.disabled = !!this.element.prop( "disabled" );
9789 } else {
9790 this.element.prop( "disabled", this.options.disabled );
9791 }
9792
9793 this._determineButtonType();
9794 this.hasTitle = !!this.buttonElement.attr( "title" );
9795
9796 var that = this,
9797 options = this.options,
9798 toggleButton = this.type === "checkbox" || this.type === "radio",
9799 activeClass = !toggleButton ? "ui-state-active" : "",
9800 focusClass = "ui-state-focus";
9801
9802 if ( options.label === null ) {
9803 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
9804 }
9805
9806 this._hoverable( this.buttonElement );
9807
9808 this.buttonElement
9809 .addClass( baseClasses )
9810 .attr( "role", "button" )
9811 .bind( "mouseenter" + this.eventNamespace, function() {
9812 if ( options.disabled ) {
9813 return;
9814 }
9815 if ( this === lastActive ) {
9816 $( this ).addClass( "ui-state-active" );
9817 }
9818 })
9819 .bind( "mouseleave" + this.eventNamespace, function() {
9820 if ( options.disabled ) {
9821 return;
9822 }
9823 $( this ).removeClass( activeClass );
9824 })
9825 .bind( "click" + this.eventNamespace, function( event ) {
9826 if ( options.disabled ) {
9827 event.preventDefault();
9828 event.stopImmediatePropagation();
9829 }
9830 });
9831
9832 this.element
9833 .bind( "focus" + this.eventNamespace, function() {
9834 // no need to check disabled, focus won't be triggered anyway
9835 that.buttonElement.addClass( focusClass );
9836 })
9837 .bind( "blur" + this.eventNamespace, function() {
9838 that.buttonElement.removeClass( focusClass );
9839 });
9840
9841 if ( toggleButton ) {
9842 this.element.bind( "change" + this.eventNamespace, function() {
9843 if ( clickDragged ) {
9844 return;
9845 }
9846 that.refresh();
9847 });
9848 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
9849 // prevents issue where button state changes but checkbox/radio checked state
9850 // does not in Firefox (see ticket #6970)
9851 this.buttonElement
9852 .bind( "mousedown" + this.eventNamespace, function( event ) {
9853 if ( options.disabled ) {
9854 return;
9855 }
9856 clickDragged = false;
9857 startXPos = event.pageX;
9858 startYPos = event.pageY;
9859 })
9860 .bind( "mouseup" + this.eventNamespace, function( event ) {
9861 if ( options.disabled ) {
9862 return;
9863 }
9864 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
9865 clickDragged = true;
9866 }
9867 });
9868 }
9869
9870 if ( this.type === "checkbox" ) {
9871 this.buttonElement.bind( "click" + this.eventNamespace, function() {
9872 if ( options.disabled || clickDragged ) {
9873 return false;
9874 }
9875 });
9876 } else if ( this.type === "radio" ) {
9877 this.buttonElement.bind( "click" + this.eventNamespace, function() {
9878 if ( options.disabled || clickDragged ) {
9879 return false;
9880 }
9881 $( this ).addClass( "ui-state-active" );
9882 that.buttonElement.attr( "aria-pressed", "true" );
9883
9884 var radio = that.element[ 0 ];
9885 radioGroup( radio )
9886 .not( radio )
9887 .map(function() {
9888 return $( this ).button( "widget" )[ 0 ];
9889 })
9890 .removeClass( "ui-state-active" )
9891 .attr( "aria-pressed", "false" );
9892 });
9893 } else {
9894 this.buttonElement
9895 .bind( "mousedown" + this.eventNamespace, function() {
9896 if ( options.disabled ) {
9897 return false;
9898 }
9899 $( this ).addClass( "ui-state-active" );
9900 lastActive = this;
9901 that.document.one( "mouseup", function() {
9902 lastActive = null;
9903 });
9904 })
9905 .bind( "mouseup" + this.eventNamespace, function() {
9906 if ( options.disabled ) {
9907 return false;
9908 }
9909 $( this ).removeClass( "ui-state-active" );
9910 })
9911 .bind( "keydown" + this.eventNamespace, function(event) {
9912 if ( options.disabled ) {
9913 return false;
9914 }
9915 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
9916 $( this ).addClass( "ui-state-active" );
9917 }
9918 })
9919 // see #8559, we bind to blur here in case the button element loses
9920 // focus between keydown and keyup, it would be left in an "active" state
9921 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
9922 $( this ).removeClass( "ui-state-active" );
9923 });
9924
9925 if ( this.buttonElement.is("a") ) {
9926 this.buttonElement.keyup(function(event) {
9927 if ( event.keyCode === $.ui.keyCode.SPACE ) {
9928 // TODO pass through original event correctly (just as 2nd argument doesn't work)
9929 $( this ).click();
9930 }
9931 });
9932 }
9933 }
9934
9935 // TODO: pull out $.Widget's handling for the disabled option into
9936 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
9937 // be overridden by individual plugins
9938 this._setOption( "disabled", options.disabled );
9939 this._resetButton();
9940 },
9941
9942 _determineButtonType: function() {
9943 var ancestor, labelSelector, checked;
9944
9945 if ( this.element.is("[type=checkbox]") ) {
9946 this.type = "checkbox";
9947 } else if ( this.element.is("[type=radio]") ) {
9948 this.type = "radio";
9949 } else if ( this.element.is("input") ) {
9950 this.type = "input";
9951 } else {
9952 this.type = "button";
9953 }
9954
9955 if ( this.type === "checkbox" || this.type === "radio" ) {
9956 // we don't search against the document in case the element
9957 // is disconnected from the DOM
9958 ancestor = this.element.parents().last();
9959 labelSelector = "label[for='" + this.element.attr("id") + "']";
9960 this.buttonElement = ancestor.find( labelSelector );
9961 if ( !this.buttonElement.length ) {
9962 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
9963 this.buttonElement = ancestor.filter( labelSelector );
9964 if ( !this.buttonElement.length ) {
9965 this.buttonElement = ancestor.find( labelSelector );
9966 }
9967 }
9968 this.element.addClass( "ui-helper-hidden-accessible" );
9969
9970 checked = this.element.is( ":checked" );
9971 if ( checked ) {
9972 this.buttonElement.addClass( "ui-state-active" );
9973 }
9974 this.buttonElement.prop( "aria-pressed", checked );
9975 } else {
9976 this.buttonElement = this.element;
9977 }
9978 },
9979
9980 widget: function() {
9981 return this.buttonElement;
9982 },
9983
9984 _destroy: function() {
9985 this.element
9986 .removeClass( "ui-helper-hidden-accessible" );
9987 this.buttonElement
9988 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
9989 .removeAttr( "role" )
9990 .removeAttr( "aria-pressed" )
9991 .html( this.buttonElement.find(".ui-button-text").html() );
9992
9993 if ( !this.hasTitle ) {
9994 this.buttonElement.removeAttr( "title" );
9995 }
9996 },
9997
9998 _setOption: function( key, value ) {
9999 this._super( key, value );
10000 if ( key === "disabled" ) {
10001 if ( value ) {
10002 this.element.prop( "disabled", true );
10003 } else {
10004 this.element.prop( "disabled", false );
10005 }
10006 return;
10007 }
10008 this._resetButton();
10009 },
10010
10011 refresh: function() {
10012 //See #8237 & #8828
10013 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
10014
10015 if ( isDisabled !== this.options.disabled ) {
10016 this._setOption( "disabled", isDisabled );
10017 }
10018 if ( this.type === "radio" ) {
10019 radioGroup( this.element[0] ).each(function() {
10020 if ( $( this ).is( ":checked" ) ) {
10021 $( this ).button( "widget" )
10022 .addClass( "ui-state-active" )
10023 .attr( "aria-pressed", "true" );
10024 } else {
10025 $( this ).button( "widget" )
10026 .removeClass( "ui-state-active" )
10027 .attr( "aria-pressed", "false" );
10028 }
10029 });
10030 } else if ( this.type === "checkbox" ) {
10031 if ( this.element.is( ":checked" ) ) {
10032 this.buttonElement
10033 .addClass( "ui-state-active" )
10034 .attr( "aria-pressed", "true" );
10035 } else {
10036 this.buttonElement
10037 .removeClass( "ui-state-active" )
10038 .attr( "aria-pressed", "false" );
10039 }
10040 }
10041 },
10042
10043 _resetButton: function() {
10044 if ( this.type === "input" ) {
10045 if ( this.options.label ) {
10046 this.element.val( this.options.label );
10047 }
10048 return;
10049 }
10050 var buttonElement = this.buttonElement.removeClass( typeClasses ),
10051 buttonText = $( "<span></span>", this.document[0] )
10052 .addClass( "ui-button-text" )
10053 .html( this.options.label )
10054 .appendTo( buttonElement.empty() )
10055 .text(),
10056 icons = this.options.icons,
10057 multipleIcons = icons.primary && icons.secondary,
10058 buttonClasses = [];
10059
10060 if ( icons.primary || icons.secondary ) {
10061 if ( this.options.text ) {
10062 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
10063 }
10064
10065 if ( icons.primary ) {
10066 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
10067 }
10068
10069 if ( icons.secondary ) {
10070 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
10071 }
10072
10073 if ( !this.options.text ) {
10074 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
10075
10076 if ( !this.hasTitle ) {
10077 buttonElement.attr( "title", $.trim( buttonText ) );
10078 }
10079 }
10080 } else {
10081 buttonClasses.push( "ui-button-text-only" );
10082 }
10083 buttonElement.addClass( buttonClasses.join( " " ) );
10084 }
10085 });
10086
10087 $.widget( "ui.buttonset", {
10088 version: "1.10.3",
10089 options: {
10090 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
10091 },
10092
10093 _create: function() {
10094 this.element.addClass( "ui-buttonset" );
10095 },
10096
10097 _init: function() {
10098 this.refresh();
10099 },
10100
10101 _setOption: function( key, value ) {
10102 if ( key === "disabled" ) {
10103 this.buttons.button( "option", key, value );
10104 }
10105
10106 this._super( key, value );
10107 },
10108
10109 refresh: function() {
10110 var rtl = this.element.css( "direction" ) === "rtl";
10111
10112 this.buttons = this.element.find( this.options.items )
10113 .filter( ":ui-button" )
10114 .button( "refresh" )
10115 .end()
10116 .not( ":ui-button" )
10117 .button()
10118 .end()
10119 .map(function() {
10120 return $( this ).button( "widget" )[ 0 ];
10121 })
10122 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
10123 .filter( ":first" )
10124 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
10125 .end()
10126 .filter( ":last" )
10127 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
10128 .end()
10129 .end();
10130 },
10131
10132 _destroy: function() {
10133 this.element.removeClass( "ui-buttonset" );
10134 this.buttons
10135 .map(function() {
10136 return $( this ).button( "widget" )[ 0 ];
10137 })
10138 .removeClass( "ui-corner-left ui-corner-right" )
10139 .end()
10140 .button( "destroy" );
10141 }
10142 });
10143
10144 }( jQuery ) );
10145 (function( $, undefined ) {
10146
10147 $.extend($.ui, { datepicker: { version: "1.10.3" } });
10148
10149 var PROP_NAME = "datepicker",
10150 instActive;
10151
10152 /* Date picker manager.
10153 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
10154 Settings for (groups of) date pickers are maintained in an instance object,
10155 allowing multiple different settings on the same page. */
10156
10157 function Datepicker() {
10158 this._curInst = null; // The current instance in use
10159 this._keyEvent = false; // If the last event was a key event
10160 this._disabledInputs = []; // List of date picker inputs that have been disabled
10161 this._datepickerShowing = false; // True if the popup picker is showing , false if not
10162 this._inDialog = false; // True if showing within a "dialog", false if not
10163 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
10164 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
10165 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
10166 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
10167 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
10168 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
10169 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
10170 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
10171 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
10172 this.regional = []; // Available regional settings, indexed by language code
10173 this.regional[""] = { // Default regional settings
10174 closeText: "Done", // Display text for close link
10175 prevText: "Prev", // Display text for previous month link
10176 nextText: "Next", // Display text for next month link
10177 currentText: "Today", // Display text for current month link
10178 monthNames: ["January","February","March","April","May","June",
10179 "July","August","September","October","November","December"], // Names of months for drop-down and formatting
10180 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
10181 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
10182 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
10183 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
10184 weekHeader: "Wk", // Column header for week of the year
10185 dateFormat: "mm/dd/yy", // See format options on parseDate
10186 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
10187 isRTL: false, // True if right-to-left language, false if left-to-right
10188 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
10189 yearSuffix: "" // Additional text to append to the year in the month headers
10190 };
10191 this._defaults = { // Global defaults for all the date picker instances
10192 showOn: "focus", // "focus" for popup on focus,
10193 // "button" for trigger button, or "both" for either
10194 showAnim: "fadeIn", // Name of jQuery animation for popup
10195 showOptions: {}, // Options for enhanced animations
10196 defaultDate: null, // Used when field is blank: actual date,
10197 // +/-number for offset from today, null for today
10198 appendText: "", // Display text following the input box, e.g. showing the format
10199 buttonText: "...", // Text for trigger button
10200 buttonImage: "", // URL for trigger button image
10201 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
10202 hideIfNoPrevNext: false, // True to hide next/previous month links
10203 // if not applicable, false to just disable them
10204 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
10205 gotoCurrent: false, // True if today link goes back to current selection instead
10206 changeMonth: false, // True if month can be selected directly, false if only prev/next
10207 changeYear: false, // True if year can be selected directly, false if only prev/next
10208 yearRange: "c-10:c+10", // Range of years to display in drop-down,
10209 // either relative to today's year (-nn:+nn), relative to currently displayed year
10210 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
10211 showOtherMonths: false, // True to show dates in other months, false to leave blank
10212 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
10213 showWeek: false, // True to show week of the year, false to not show it
10214 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
10215 // takes a Date and returns the number of the week for it
10216 shortYearCutoff: "+10", // Short year values < this are in the current century,
10217 // > this are in the previous century,
10218 // string value starting with "+" for current year + value
10219 minDate: null, // The earliest selectable date, or null for no limit
10220 maxDate: null, // The latest selectable date, or null for no limit
10221 duration: "fast", // Duration of display/closure
10222 beforeShowDay: null, // Function that takes a date and returns an array with
10223 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
10224 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
10225 beforeShow: null, // Function that takes an input field and
10226 // returns a set of custom settings for the date picker
10227 onSelect: null, // Define a callback function when a date is selected
10228 onChangeMonthYear: null, // Define a callback function when the month or year is changed
10229 onClose: null, // Define a callback function when the datepicker is closed
10230 numberOfMonths: 1, // Number of months to show at a time
10231 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
10232 stepMonths: 1, // Number of months to step back/forward
10233 stepBigMonths: 12, // Number of months to step back/forward for the big links
10234 altField: "", // Selector for an alternate field to store selected dates into
10235 altFormat: "", // The date format to use for the alternate field
10236 constrainInput: true, // The input is constrained by the current date format
10237 showButtonPanel: false, // True to show button panel, false to not show it
10238 autoSize: false, // True to size the input for the date format, false to leave as is
10239 disabled: false // The initial disabled state
10240 };
10241 $.extend(this._defaults, this.regional[""]);
10242 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
10243 }
10244
10245 $.extend(Datepicker.prototype, {
10246 /* Class name added to elements to indicate already configured with a date picker. */
10247 markerClassName: "hasDatepicker",
10248
10249 //Keep track of the maximum number of rows displayed (see #7043)
10250 maxRows: 4,
10251
10252 // TODO rename to "widget" when switching to widget factory
10253 _widgetDatepicker: function() {
10254 return this.dpDiv;
10255 },
10256
10257 /* Override the default settings for all instances of the date picker.
10258 * @param settings object - the new settings to use as defaults (anonymous object)
10259 * @return the manager object
10260 */
10261 setDefaults: function(settings) {
10262 extendRemove(this._defaults, settings || {});
10263 return this;
10264 },
10265
10266 /* Attach the date picker to a jQuery selection.
10267 * @param target element - the target input field or division or span
10268 * @param settings object - the new settings to use for this date picker instance (anonymous)
10269 */
10270 _attachDatepicker: function(target, settings) {
10271 var nodeName, inline, inst;
10272 nodeName = target.nodeName.toLowerCase();
10273 inline = (nodeName === "div" || nodeName === "span");
10274 if (!target.id) {
10275 this.uuid += 1;
10276 target.id = "dp" + this.uuid;
10277 }
10278 inst = this._newInst($(target), inline);
10279 inst.settings = $.extend({}, settings || {});
10280 if (nodeName === "input") {
10281 this._connectDatepicker(target, inst);
10282 } else if (inline) {
10283 this._inlineDatepicker(target, inst);
10284 }
10285 },
10286
10287 /* Create a new instance object. */
10288 _newInst: function(target, inline) {
10289 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
10290 return {id: id, input: target, // associated target
10291 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
10292 drawMonth: 0, drawYear: 0, // month being drawn
10293 inline: inline, // is datepicker inline or not
10294 dpDiv: (!inline ? this.dpDiv : // presentation div
10295 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
10296 },
10297
10298 /* Attach the date picker to an input field. */
10299 _connectDatepicker: function(target, inst) {
10300 var input = $(target);
10301 inst.append = $([]);
10302 inst.trigger = $([]);
10303 if (input.hasClass(this.markerClassName)) {
10304 return;
10305 }
10306 this._attachments(input, inst);
10307 input.addClass(this.markerClassName).keydown(this._doKeyDown).
10308 keypress(this._doKeyPress).keyup(this._doKeyUp);
10309 this._autoSize(inst);
10310 $.data(target, PROP_NAME, inst);
10311 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
10312 if( inst.settings.disabled ) {
10313 this._disableDatepicker( target );
10314 }
10315 },
10316
10317 /* Make attachments based on settings. */
10318 _attachments: function(input, inst) {
10319 var showOn, buttonText, buttonImage,
10320 appendText = this._get(inst, "appendText"),
10321 isRTL = this._get(inst, "isRTL");
10322
10323 if (inst.append) {
10324 inst.append.remove();
10325 }
10326 if (appendText) {
10327 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
10328 input[isRTL ? "before" : "after"](inst.append);
10329 }
10330
10331 input.unbind("focus", this._showDatepicker);
10332
10333 if (inst.trigger) {
10334 inst.trigger.remove();
10335 }
10336
10337 showOn = this._get(inst, "showOn");
10338 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
10339 input.focus(this._showDatepicker);
10340 }
10341 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
10342 buttonText = this._get(inst, "buttonText");
10343 buttonImage = this._get(inst, "buttonImage");
10344 inst.trigger = $(this._get(inst, "buttonImageOnly") ?
10345 $("<img/>").addClass(this._triggerClass).
10346 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
10347 $("<button type='button'></button>").addClass(this._triggerClass).
10348 html(!buttonImage ? buttonText : $("<img/>").attr(
10349 { src:buttonImage, alt:buttonText, title:buttonText })));
10350 input[isRTL ? "before" : "after"](inst.trigger);
10351 inst.trigger.click(function() {
10352 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
10353 $.datepicker._hideDatepicker();
10354 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
10355 $.datepicker._hideDatepicker();
10356 $.datepicker._showDatepicker(input[0]);
10357 } else {
10358 $.datepicker._showDatepicker(input[0]);
10359 }
10360 return false;
10361 });
10362 }
10363 },
10364
10365 /* Apply the maximum length for the date format. */
10366 _autoSize: function(inst) {
10367 if (this._get(inst, "autoSize") && !inst.inline) {
10368 var findMax, max, maxI, i,
10369 date = new Date(2009, 12 - 1, 20), // Ensure double digits
10370 dateFormat = this._get(inst, "dateFormat");
10371
10372 if (dateFormat.match(/[DM]/)) {
10373 findMax = function(names) {
10374 max = 0;
10375 maxI = 0;
10376 for (i = 0; i < names.length; i++) {
10377 if (names[i].length > max) {
10378 max = names[i].length;
10379 maxI = i;
10380 }
10381 }
10382 return maxI;
10383 };
10384 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
10385 "monthNames" : "monthNamesShort"))));
10386 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
10387 "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
10388 }
10389 inst.input.attr("size", this._formatDate(inst, date).length);
10390 }
10391 },
10392
10393 /* Attach an inline date picker to a div. */
10394 _inlineDatepicker: function(target, inst) {
10395 var divSpan = $(target);
10396 if (divSpan.hasClass(this.markerClassName)) {
10397 return;
10398 }
10399 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
10400 $.data(target, PROP_NAME, inst);
10401 this._setDate(inst, this._getDefaultDate(inst), true);
10402 this._updateDatepicker(inst);
10403 this._updateAlternate(inst);
10404 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
10405 if( inst.settings.disabled ) {
10406 this._disableDatepicker( target );
10407 }
10408 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
10409 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
10410 inst.dpDiv.css( "display", "block" );
10411 },
10412
10413 /* Pop-up the date picker in a "dialog" box.
10414 * @param input element - ignored
10415 * @param date string or Date - the initial date to display
10416 * @param onSelect function - the function to call when a date is selected
10417 * @param settings object - update the dialog date picker instance's settings (anonymous object)
10418 * @param pos int[2] - coordinates for the dialog's position within the screen or
10419 * event - with x/y coordinates or
10420 * leave empty for default (screen centre)
10421 * @return the manager object
10422 */
10423 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
10424 var id, browserWidth, browserHeight, scrollX, scrollY,
10425 inst = this._dialogInst; // internal instance
10426
10427 if (!inst) {
10428 this.uuid += 1;
10429 id = "dp" + this.uuid;
10430 this._dialogInput = $("<input type='text' id='" + id +
10431 "' style='position: absolute; top: -100px; width: 0px;'/>");
10432 this._dialogInput.keydown(this._doKeyDown);
10433 $("body").append(this._dialogInput);
10434 inst = this._dialogInst = this._newInst(this._dialogInput, false);
10435 inst.settings = {};
10436 $.data(this._dialogInput[0], PROP_NAME, inst);
10437 }
10438 extendRemove(inst.settings, settings || {});
10439 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
10440 this._dialogInput.val(date);
10441
10442 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
10443 if (!this._pos) {
10444 browserWidth = document.documentElement.clientWidth;
10445 browserHeight = document.documentElement.clientHeight;
10446 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
10447 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
10448 this._pos = // should use actual width/height below
10449 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
10450 }
10451
10452 // move input on screen for focus, but hidden behind dialog
10453 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
10454 inst.settings.onSelect = onSelect;
10455 this._inDialog = true;
10456 this.dpDiv.addClass(this._dialogClass);
10457 this._showDatepicker(this._dialogInput[0]);
10458 if ($.blockUI) {
10459 $.blockUI(this.dpDiv);
10460 }
10461 $.data(this._dialogInput[0], PROP_NAME, inst);
10462 return this;
10463 },
10464
10465 /* Detach a datepicker from its control.
10466 * @param target element - the target input field or division or span
10467 */
10468 _destroyDatepicker: function(target) {
10469 var nodeName,
10470 $target = $(target),
10471 inst = $.data(target, PROP_NAME);
10472
10473 if (!$target.hasClass(this.markerClassName)) {
10474 return;
10475 }
10476
10477 nodeName = target.nodeName.toLowerCase();
10478 $.removeData(target, PROP_NAME);
10479 if (nodeName === "input") {
10480 inst.append.remove();
10481 inst.trigger.remove();
10482 $target.removeClass(this.markerClassName).
10483 unbind("focus", this._showDatepicker).
10484 unbind("keydown", this._doKeyDown).
10485 unbind("keypress", this._doKeyPress).
10486 unbind("keyup", this._doKeyUp);
10487 } else if (nodeName === "div" || nodeName === "span") {
10488 $target.removeClass(this.markerClassName).empty();
10489 }
10490 },
10491
10492 /* Enable the date picker to a jQuery selection.
10493 * @param target element - the target input field or division or span
10494 */
10495 _enableDatepicker: function(target) {
10496 var nodeName, inline,
10497 $target = $(target),
10498 inst = $.data(target, PROP_NAME);
10499
10500 if (!$target.hasClass(this.markerClassName)) {
10501 return;
10502 }
10503
10504 nodeName = target.nodeName.toLowerCase();
10505 if (nodeName === "input") {
10506 target.disabled = false;
10507 inst.trigger.filter("button").
10508 each(function() { this.disabled = false; }).end().
10509 filter("img").css({opacity: "1.0", cursor: ""});
10510 } else if (nodeName === "div" || nodeName === "span") {
10511 inline = $target.children("." + this._inlineClass);
10512 inline.children().removeClass("ui-state-disabled");
10513 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
10514 prop("disabled", false);
10515 }
10516 this._disabledInputs = $.map(this._disabledInputs,
10517 function(value) { return (value === target ? null : value); }); // delete entry
10518 },
10519
10520 /* Disable the date picker to a jQuery selection.
10521 * @param target element - the target input field or division or span
10522 */
10523 _disableDatepicker: function(target) {
10524 var nodeName, inline,
10525 $target = $(target),
10526 inst = $.data(target, PROP_NAME);
10527
10528 if (!$target.hasClass(this.markerClassName)) {
10529 return;
10530 }
10531
10532 nodeName = target.nodeName.toLowerCase();
10533 if (nodeName === "input") {
10534 target.disabled = true;
10535 inst.trigger.filter("button").
10536 each(function() { this.disabled = true; }).end().
10537 filter("img").css({opacity: "0.5", cursor: "default"});
10538 } else if (nodeName === "div" || nodeName === "span") {
10539 inline = $target.children("." + this._inlineClass);
10540 inline.children().addClass("ui-state-disabled");
10541 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
10542 prop("disabled", true);
10543 }
10544 this._disabledInputs = $.map(this._disabledInputs,
10545 function(value) { return (value === target ? null : value); }); // delete entry
10546 this._disabledInputs[this._disabledInputs.length] = target;
10547 },
10548
10549 /* Is the first field in a jQuery collection disabled as a datepicker?
10550 * @param target element - the target input field or division or span
10551 * @return boolean - true if disabled, false if enabled
10552 */
10553 _isDisabledDatepicker: function(target) {
10554 if (!target) {
10555 return false;
10556 }
10557 for (var i = 0; i < this._disabledInputs.length; i++) {
10558 if (this._disabledInputs[i] === target) {
10559 return true;
10560 }
10561 }
10562 return false;
10563 },
10564
10565 /* Retrieve the instance data for the target control.
10566 * @param target element - the target input field or division or span
10567 * @return object - the associated instance data
10568 * @throws error if a jQuery problem getting data
10569 */
10570 _getInst: function(target) {
10571 try {
10572 return $.data(target, PROP_NAME);
10573 }
10574 catch (err) {
10575 throw "Missing instance data for this datepicker";
10576 }
10577 },
10578
10579 /* Update or retrieve the settings for a date picker attached to an input field or division.
10580 * @param target element - the target input field or division or span
10581 * @param name object - the new settings to update or
10582 * string - the name of the setting to change or retrieve,
10583 * when retrieving also "all" for all instance settings or
10584 * "defaults" for all global defaults
10585 * @param value any - the new value for the setting
10586 * (omit if above is an object or to retrieve a value)
10587 */
10588 _optionDatepicker: function(target, name, value) {
10589 var settings, date, minDate, maxDate,
10590 inst = this._getInst(target);
10591
10592 if (arguments.length === 2 && typeof name === "string") {
10593 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
10594 (inst ? (name === "all" ? $.extend({}, inst.settings) :
10595 this._get(inst, name)) : null));
10596 }
10597
10598 settings = name || {};
10599 if (typeof name === "string") {
10600 settings = {};
10601 settings[name] = value;
10602 }
10603
10604 if (inst) {
10605 if (this._curInst === inst) {
10606 this._hideDatepicker();
10607 }
10608
10609 date = this._getDateDatepicker(target, true);
10610 minDate = this._getMinMaxDate(inst, "min");
10611 maxDate = this._getMinMaxDate(inst, "max");
10612 extendRemove(inst.settings, settings);
10613 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
10614 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
10615 inst.settings.minDate = this._formatDate(inst, minDate);
10616 }
10617 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
10618 inst.settings.maxDate = this._formatDate(inst, maxDate);
10619 }
10620 if ( "disabled" in settings ) {
10621 if ( settings.disabled ) {
10622 this._disableDatepicker(target);
10623 } else {
10624 this._enableDatepicker(target);
10625 }
10626 }
10627 this._attachments($(target), inst);
10628 this._autoSize(inst);
10629 this._setDate(inst, date);
10630 this._updateAlternate(inst);
10631 this._updateDatepicker(inst);
10632 }
10633 },
10634
10635 // change method deprecated
10636 _changeDatepicker: function(target, name, value) {
10637 this._optionDatepicker(target, name, value);
10638 },
10639
10640 /* Redraw the date picker attached to an input field or division.
10641 * @param target element - the target input field or division or span
10642 */
10643 _refreshDatepicker: function(target) {
10644 var inst = this._getInst(target);
10645 if (inst) {
10646 this._updateDatepicker(inst);
10647 }
10648 },
10649
10650 /* Set the dates for a jQuery selection.
10651 * @param target element - the target input field or division or span
10652 * @param date Date - the new date
10653 */
10654 _setDateDatepicker: function(target, date) {
10655 var inst = this._getInst(target);
10656 if (inst) {
10657 this._setDate(inst, date);
10658 this._updateDatepicker(inst);
10659 this._updateAlternate(inst);
10660 }
10661 },
10662
10663 /* Get the date(s) for the first entry in a jQuery selection.
10664 * @param target element - the target input field or division or span
10665 * @param noDefault boolean - true if no default date is to be used
10666 * @return Date - the current date
10667 */
10668 _getDateDatepicker: function(target, noDefault) {
10669 var inst = this._getInst(target);
10670 if (inst && !inst.inline) {
10671 this._setDateFromField(inst, noDefault);
10672 }
10673 return (inst ? this._getDate(inst) : null);
10674 },
10675
10676 /* Handle keystrokes. */
10677 _doKeyDown: function(event) {
10678 var onSelect, dateStr, sel,
10679 inst = $.datepicker._getInst(event.target),
10680 handled = true,
10681 isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
10682
10683 inst._keyEvent = true;
10684 if ($.datepicker._datepickerShowing) {
10685 switch (event.keyCode) {
10686 case 9: $.datepicker._hideDatepicker();
10687 handled = false;
10688 break; // hide on tab out
10689 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
10690 $.datepicker._currentClass + ")", inst.dpDiv);
10691 if (sel[0]) {
10692 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
10693 }
10694
10695 onSelect = $.datepicker._get(inst, "onSelect");
10696 if (onSelect) {
10697 dateStr = $.datepicker._formatDate(inst);
10698
10699 // trigger custom callback
10700 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
10701 } else {
10702 $.datepicker._hideDatepicker();
10703 }
10704
10705 return false; // don't submit the form
10706 case 27: $.datepicker._hideDatepicker();
10707 break; // hide on escape
10708 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
10709 -$.datepicker._get(inst, "stepBigMonths") :
10710 -$.datepicker._get(inst, "stepMonths")), "M");
10711 break; // previous month/year on page up/+ ctrl
10712 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
10713 +$.datepicker._get(inst, "stepBigMonths") :
10714 +$.datepicker._get(inst, "stepMonths")), "M");
10715 break; // next month/year on page down/+ ctrl
10716 case 35: if (event.ctrlKey || event.metaKey) {
10717 $.datepicker._clearDate(event.target);
10718 }
10719 handled = event.ctrlKey || event.metaKey;
10720 break; // clear on ctrl or command +end
10721 case 36: if (event.ctrlKey || event.metaKey) {
10722 $.datepicker._gotoToday(event.target);
10723 }
10724 handled = event.ctrlKey || event.metaKey;
10725 break; // current on ctrl or command +home
10726 case 37: if (event.ctrlKey || event.metaKey) {
10727 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
10728 }
10729 handled = event.ctrlKey || event.metaKey;
10730 // -1 day on ctrl or command +left
10731 if (event.originalEvent.altKey) {
10732 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
10733 -$.datepicker._get(inst, "stepBigMonths") :
10734 -$.datepicker._get(inst, "stepMonths")), "M");
10735 }
10736 // next month/year on alt +left on Mac
10737 break;
10738 case 38: if (event.ctrlKey || event.metaKey) {
10739 $.datepicker._adjustDate(event.target, -7, "D");
10740 }
10741 handled = event.ctrlKey || event.metaKey;
10742 break; // -1 week on ctrl or command +up
10743 case 39: if (event.ctrlKey || event.metaKey) {
10744 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
10745 }
10746 handled = event.ctrlKey || event.metaKey;
10747 // +1 day on ctrl or command +right
10748 if (event.originalEvent.altKey) {
10749 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
10750 +$.datepicker._get(inst, "stepBigMonths") :
10751 +$.datepicker._get(inst, "stepMonths")), "M");
10752 }
10753 // next month/year on alt +right
10754 break;
10755 case 40: if (event.ctrlKey || event.metaKey) {
10756 $.datepicker._adjustDate(event.target, +7, "D");
10757 }
10758 handled = event.ctrlKey || event.metaKey;
10759 break; // +1 week on ctrl or command +down
10760 default: handled = false;
10761 }
10762 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
10763 $.datepicker._showDatepicker(this);
10764 } else {
10765 handled = false;
10766 }
10767
10768 if (handled) {
10769 event.preventDefault();
10770 event.stopPropagation();
10771 }
10772 },
10773
10774 /* Filter entered characters - based on date format. */
10775 _doKeyPress: function(event) {
10776 var chars, chr,
10777 inst = $.datepicker._getInst(event.target);
10778
10779 if ($.datepicker._get(inst, "constrainInput")) {
10780 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
10781 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
10782 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
10783 }
10784 },
10785
10786 /* Synchronise manual entry and field/alternate field. */
10787 _doKeyUp: function(event) {
10788 var date,
10789 inst = $.datepicker._getInst(event.target);
10790
10791 if (inst.input.val() !== inst.lastVal) {
10792 try {
10793 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
10794 (inst.input ? inst.input.val() : null),
10795 $.datepicker._getFormatConfig(inst));
10796
10797 if (date) { // only if valid
10798 $.datepicker._setDateFromField(inst);
10799 $.datepicker._updateAlternate(inst);
10800 $.datepicker._updateDatepicker(inst);
10801 }
10802 }
10803 catch (err) {
10804 }
10805 }
10806 return true;
10807 },
10808
10809 /* Pop-up the date picker for a given input field.
10810 * If false returned from beforeShow event handler do not show.
10811 * @param input element - the input field attached to the date picker or
10812 * event - if triggered by focus
10813 */
10814 _showDatepicker: function(input) {
10815 input = input.target || input;
10816 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
10817 input = $("input", input.parentNode)[0];
10818 }
10819
10820 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
10821 return;
10822 }
10823
10824 var inst, beforeShow, beforeShowSettings, isFixed,
10825 offset, showAnim, duration;
10826
10827 inst = $.datepicker._getInst(input);
10828 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
10829 $.datepicker._curInst.dpDiv.stop(true, true);
10830 if ( inst && $.datepicker._datepickerShowing ) {
10831 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
10832 }
10833 }
10834
10835 beforeShow = $.datepicker._get(inst, "beforeShow");
10836 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
10837 if(beforeShowSettings === false){
10838 return;
10839 }
10840 extendRemove(inst.settings, beforeShowSettings);
10841
10842 inst.lastVal = null;
10843 $.datepicker._lastInput = input;
10844 $.datepicker._setDateFromField(inst);
10845
10846 if ($.datepicker._inDialog) { // hide cursor
10847 input.value = "";
10848 }
10849 if (!$.datepicker._pos) { // position below input
10850 $.datepicker._pos = $.datepicker._findPos(input);
10851 $.datepicker._pos[1] += input.offsetHeight; // add the height
10852 }
10853
10854 isFixed = false;
10855 $(input).parents().each(function() {
10856 isFixed |= $(this).css("position") === "fixed";
10857 return !isFixed;
10858 });
10859
10860 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
10861 $.datepicker._pos = null;
10862 //to avoid flashes on Firefox
10863 inst.dpDiv.empty();
10864 // determine sizing offscreen
10865 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
10866 $.datepicker._updateDatepicker(inst);
10867 // fix width for dynamic number of date pickers
10868 // and adjust position before showing
10869 offset = $.datepicker._checkOffset(inst, offset, isFixed);
10870 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
10871 "static" : (isFixed ? "fixed" : "absolute")), display: "none",
10872 left: offset.left + "px", top: offset.top + "px"});
10873
10874 if (!inst.inline) {
10875 showAnim = $.datepicker._get(inst, "showAnim");
10876 duration = $.datepicker._get(inst, "duration");
10877 inst.dpDiv.zIndex($(input).zIndex()+1);
10878 $.datepicker._datepickerShowing = true;
10879
10880 if ( $.effects && $.effects.effect[ showAnim ] ) {
10881 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
10882 } else {
10883 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
10884 }
10885
10886 if ( $.datepicker._shouldFocusInput( inst ) ) {
10887 inst.input.focus();
10888 }
10889
10890 $.datepicker._curInst = inst;
10891 }
10892 },
10893
10894 /* Generate the date picker content. */
10895 _updateDatepicker: function(inst) {
10896 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
10897 instActive = inst; // for delegate hover events
10898 inst.dpDiv.empty().append(this._generateHTML(inst));
10899 this._attachHandlers(inst);
10900 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
10901
10902 var origyearshtml,
10903 numMonths = this._getNumberOfMonths(inst),
10904 cols = numMonths[1],
10905 width = 17;
10906
10907 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
10908 if (cols > 1) {
10909 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
10910 }
10911 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
10912 "Class"]("ui-datepicker-multi");
10913 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
10914 "Class"]("ui-datepicker-rtl");
10915
10916 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
10917 inst.input.focus();
10918 }
10919
10920 // deffered render of the years select (to avoid flashes on Firefox)
10921 if( inst.yearshtml ){
10922 origyearshtml = inst.yearshtml;
10923 setTimeout(function(){
10924 //assure that inst.yearshtml didn't change.
10925 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
10926 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
10927 }
10928 origyearshtml = inst.yearshtml = null;
10929 }, 0);
10930 }
10931 },
10932
10933 // #6694 - don't focus the input if it's already focused
10934 // this breaks the change event in IE
10935 // Support: IE and jQuery <1.9
10936 _shouldFocusInput: function( inst ) {
10937 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
10938 },
10939
10940 /* Check positioning to remain on screen. */
10941 _checkOffset: function(inst, offset, isFixed) {
10942 var dpWidth = inst.dpDiv.outerWidth(),
10943 dpHeight = inst.dpDiv.outerHeight(),
10944 inputWidth = inst.input ? inst.input.outerWidth() : 0,
10945 inputHeight = inst.input ? inst.input.outerHeight() : 0,
10946 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
10947 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
10948
10949 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
10950 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
10951 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
10952
10953 // now check if datepicker is showing outside window viewport - move to a better place if so.
10954 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
10955 Math.abs(offset.left + dpWidth - viewWidth) : 0);
10956 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
10957 Math.abs(dpHeight + inputHeight) : 0);
10958
10959 return offset;
10960 },
10961
10962 /* Find an object's position on the screen. */
10963 _findPos: function(obj) {
10964 var position,
10965 inst = this._getInst(obj),
10966 isRTL = this._get(inst, "isRTL");
10967
10968 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
10969 obj = obj[isRTL ? "previousSibling" : "nextSibling"];
10970 }
10971
10972 position = $(obj).offset();
10973 return [position.left, position.top];
10974 },
10975
10976 /* Hide the date picker from view.
10977 * @param input element - the input field attached to the date picker
10978 */
10979 _hideDatepicker: function(input) {
10980 var showAnim, duration, postProcess, onClose,
10981 inst = this._curInst;
10982
10983 if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
10984 return;
10985 }
10986
10987 if (this._datepickerShowing) {
10988 showAnim = this._get(inst, "showAnim");
10989 duration = this._get(inst, "duration");
10990 postProcess = function() {
10991 $.datepicker._tidyDialog(inst);
10992 };
10993
10994 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
10995 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
10996 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
10997 } else {
10998 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
10999 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
11000 }
11001
11002 if (!showAnim) {
11003 postProcess();
11004 }
11005 this._datepickerShowing = false;
11006
11007 onClose = this._get(inst, "onClose");
11008 if (onClose) {
11009 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
11010 }
11011
11012 this._lastInput = null;
11013 if (this._inDialog) {
11014 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
11015 if ($.blockUI) {
11016 $.unblockUI();
11017 $("body").append(this.dpDiv);
11018 }
11019 }
11020 this._inDialog = false;
11021 }
11022 },
11023
11024 /* Tidy up after a dialog display. */
11025 _tidyDialog: function(inst) {
11026 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
11027 },
11028
11029 /* Close date picker if clicked elsewhere. */
11030 _checkExternalClick: function(event) {
11031 if (!$.datepicker._curInst) {
11032 return;
11033 }
11034
11035 var $target = $(event.target),
11036 inst = $.datepicker._getInst($target[0]);
11037
11038 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
11039 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
11040 !$target.hasClass($.datepicker.markerClassName) &&
11041 !$target.closest("." + $.datepicker._triggerClass).length &&
11042 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
11043 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
11044 $.datepicker._hideDatepicker();
11045 }
11046 },
11047
11048 /* Adjust one of the date sub-fields. */
11049 _adjustDate: function(id, offset, period) {
11050 var target = $(id),
11051 inst = this._getInst(target[0]);
11052
11053 if (this._isDisabledDatepicker(target[0])) {
11054 return;
11055 }
11056 this._adjustInstDate(inst, offset +
11057 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
11058 period);
11059 this._updateDatepicker(inst);
11060 },
11061
11062 /* Action for current link. */
11063 _gotoToday: function(id) {
11064 var date,
11065 target = $(id),
11066 inst = this._getInst(target[0]);
11067
11068 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
11069 inst.selectedDay = inst.currentDay;
11070 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
11071 inst.drawYear = inst.selectedYear = inst.currentYear;
11072 } else {
11073 date = new Date();
11074 inst.selectedDay = date.getDate();
11075 inst.drawMonth = inst.selectedMonth = date.getMonth();
11076 inst.drawYear = inst.selectedYear = date.getFullYear();
11077 }
11078 this._notifyChange(inst);
11079 this._adjustDate(target);
11080 },
11081
11082 /* Action for selecting a new month/year. */
11083 _selectMonthYear: function(id, select, period) {
11084 var target = $(id),
11085 inst = this._getInst(target[0]);
11086
11087 inst["selected" + (period === "M" ? "Month" : "Year")] =
11088 inst["draw" + (period === "M" ? "Month" : "Year")] =
11089 parseInt(select.options[select.selectedIndex].value,10);
11090
11091 this._notifyChange(inst);
11092 this._adjustDate(target);
11093 },
11094
11095 /* Action for selecting a day. */
11096 _selectDay: function(id, month, year, td) {
11097 var inst,
11098 target = $(id);
11099
11100 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
11101 return;
11102 }
11103
11104 inst = this._getInst(target[0]);
11105 inst.selectedDay = inst.currentDay = $("a", td).html();
11106 inst.selectedMonth = inst.currentMonth = month;
11107 inst.selectedYear = inst.currentYear = year;
11108 this._selectDate(id, this._formatDate(inst,
11109 inst.currentDay, inst.currentMonth, inst.currentYear));
11110 },
11111
11112 /* Erase the input field and hide the date picker. */
11113 _clearDate: function(id) {
11114 var target = $(id);
11115 this._selectDate(target, "");
11116 },
11117
11118 /* Update the input field with the selected date. */
11119 _selectDate: function(id, dateStr) {
11120 var onSelect,
11121 target = $(id),
11122 inst = this._getInst(target[0]);
11123
11124 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
11125 if (inst.input) {
11126 inst.input.val(dateStr);
11127 }
11128 this._updateAlternate(inst);
11129
11130 onSelect = this._get(inst, "onSelect");
11131 if (onSelect) {
11132 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
11133 } else if (inst.input) {
11134 inst.input.trigger("change"); // fire the change event
11135 }
11136
11137 if (inst.inline){
11138 this._updateDatepicker(inst);
11139 } else {
11140 this._hideDatepicker();
11141 this._lastInput = inst.input[0];
11142 if (typeof(inst.input[0]) !== "object") {
11143 inst.input.focus(); // restore focus
11144 }
11145 this._lastInput = null;
11146 }
11147 },
11148
11149 /* Update any alternate field to synchronise with the main field. */
11150 _updateAlternate: function(inst) {
11151 var altFormat, date, dateStr,
11152 altField = this._get(inst, "altField");
11153
11154 if (altField) { // update alternate field too
11155 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
11156 date = this._getDate(inst);
11157 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
11158 $(altField).each(function() { $(this).val(dateStr); });
11159 }
11160 },
11161
11162 /* Set as beforeShowDay function to prevent selection of weekends.
11163 * @param date Date - the date to customise
11164 * @return [boolean, string] - is this date selectable?, what is its CSS class?
11165 */
11166 noWeekends: function(date) {
11167 var day = date.getDay();
11168 return [(day > 0 && day < 6), ""];
11169 },
11170
11171 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
11172 * @param date Date - the date to get the week for
11173 * @return number - the number of the week within the year that contains this date
11174 */
11175 iso8601Week: function(date) {
11176 var time,
11177 checkDate = new Date(date.getTime());
11178
11179 // Find Thursday of this week starting on Monday
11180 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
11181
11182 time = checkDate.getTime();
11183 checkDate.setMonth(0); // Compare with Jan 1
11184 checkDate.setDate(1);
11185 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
11186 },
11187
11188 /* Parse a string value into a date object.
11189 * See formatDate below for the possible formats.
11190 *
11191 * @param format string - the expected format of the date
11192 * @param value string - the date in the above format
11193 * @param settings Object - attributes include:
11194 * shortYearCutoff number - the cutoff year for determining the century (optional)
11195 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
11196 * dayNames string[7] - names of the days from Sunday (optional)
11197 * monthNamesShort string[12] - abbreviated names of the months (optional)
11198 * monthNames string[12] - names of the months (optional)
11199 * @return Date - the extracted date value or null if value is blank
11200 */
11201 parseDate: function (format, value, settings) {
11202 if (format == null || value == null) {
11203 throw "Invalid arguments";
11204 }
11205
11206 value = (typeof value === "object" ? value.toString() : value + "");
11207 if (value === "") {
11208 return null;
11209 }
11210
11211 var iFormat, dim, extra,
11212 iValue = 0,
11213 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
11214 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
11215 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
11216 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
11217 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
11218 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
11219 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
11220 year = -1,
11221 month = -1,
11222 day = -1,
11223 doy = -1,
11224 literal = false,
11225 date,
11226 // Check whether a format character is doubled
11227 lookAhead = function(match) {
11228 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
11229 if (matches) {
11230 iFormat++;
11231 }
11232 return matches;
11233 },
11234 // Extract a number from the string value
11235 getNumber = function(match) {
11236 var isDoubled = lookAhead(match),
11237 size = (match === "@" ? 14 : (match === "!" ? 20 :
11238 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
11239 digits = new RegExp("^\\d{1," + size + "}"),
11240 num = value.substring(iValue).match(digits);
11241 if (!num) {
11242 throw "Missing number at position " + iValue;
11243 }
11244 iValue += num[0].length;
11245 return parseInt(num[0], 10);
11246 },
11247 // Extract a name from the string value and convert to an index
11248 getName = function(match, shortNames, longNames) {
11249 var index = -1,
11250 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
11251 return [ [k, v] ];
11252 }).sort(function (a, b) {
11253 return -(a[1].length - b[1].length);
11254 });
11255
11256 $.each(names, function (i, pair) {
11257 var name = pair[1];
11258 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
11259 index = pair[0];
11260 iValue += name.length;
11261 return false;
11262 }
11263 });
11264 if (index !== -1) {
11265 return index + 1;
11266 } else {
11267 throw "Unknown name at position " + iValue;
11268 }
11269 },
11270 // Confirm that a literal character matches the string value
11271 checkLiteral = function() {
11272 if (value.charAt(iValue) !== format.charAt(iFormat)) {
11273 throw "Unexpected literal at position " + iValue;
11274 }
11275 iValue++;
11276 };
11277
11278 for (iFormat = 0; iFormat < format.length; iFormat++) {
11279 if (literal) {
11280 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
11281 literal = false;
11282 } else {
11283 checkLiteral();
11284 }
11285 } else {
11286 switch (format.charAt(iFormat)) {
11287 case "d":
11288 day = getNumber("d");
11289 break;
11290 case "D":
11291 getName("D", dayNamesShort, dayNames);
11292 break;
11293 case "o":
11294 doy = getNumber("o");
11295 break;
11296 case "m":
11297 month = getNumber("m");
11298 break;
11299 case "M":
11300 month = getName("M", monthNamesShort, monthNames);
11301 break;
11302 case "y":
11303 year = getNumber("y");
11304 break;
11305 case "@":
11306 date = new Date(getNumber("@"));
11307 year = date.getFullYear();
11308 month = date.getMonth() + 1;
11309 day = date.getDate();
11310 break;
11311 case "!":
11312 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
11313 year = date.getFullYear();
11314 month = date.getMonth() + 1;
11315 day = date.getDate();
11316 break;
11317 case "'":
11318 if (lookAhead("'")){
11319 checkLiteral();
11320 } else {
11321 literal = true;
11322 }
11323 break;
11324 default:
11325 checkLiteral();
11326 }
11327 }
11328 }
11329
11330 if (iValue < value.length){
11331 extra = value.substr(iValue);
11332 if (!/^\s+/.test(extra)) {
11333 throw "Extra/unparsed characters found in date: " + extra;
11334 }
11335 }
11336
11337 if (year === -1) {
11338 year = new Date().getFullYear();
11339 } else if (year < 100) {
11340 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
11341 (year <= shortYearCutoff ? 0 : -100);
11342 }
11343
11344 if (doy > -1) {
11345 month = 1;
11346 day = doy;
11347 do {
11348 dim = this._getDaysInMonth(year, month - 1);
11349 if (day <= dim) {
11350 break;
11351 }
11352 month++;
11353 day -= dim;
11354 } while (true);
11355 }
11356
11357 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
11358 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
11359 throw "Invalid date"; // E.g. 31/02/00
11360 }
11361 return date;
11362 },
11363
11364 /* Standard date formats. */
11365 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
11366 COOKIE: "D, dd M yy",
11367 ISO_8601: "yy-mm-dd",
11368 RFC_822: "D, d M y",
11369 RFC_850: "DD, dd-M-y",
11370 RFC_1036: "D, d M y",
11371 RFC_1123: "D, d M yy",
11372 RFC_2822: "D, d M yy",
11373 RSS: "D, d M y", // RFC 822
11374 TICKS: "!",
11375 TIMESTAMP: "@",
11376 W3C: "yy-mm-dd", // ISO 8601
11377
11378 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
11379 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
11380
11381 /* Format a date object into a string value.
11382 * The format can be combinations of the following:
11383 * d - day of month (no leading zero)
11384 * dd - day of month (two digit)
11385 * o - day of year (no leading zeros)
11386 * oo - day of year (three digit)
11387 * D - day name short
11388 * DD - day name long
11389 * m - month of year (no leading zero)
11390 * mm - month of year (two digit)
11391 * M - month name short
11392 * MM - month name long
11393 * y - year (two digit)
11394 * yy - year (four digit)
11395 * @ - Unix timestamp (ms since 01/01/1970)
11396 * ! - Windows ticks (100ns since 01/01/0001)
11397 * "..." - literal text
11398 * '' - single quote
11399 *
11400 * @param format string - the desired format of the date
11401 * @param date Date - the date value to format
11402 * @param settings Object - attributes include:
11403 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
11404 * dayNames string[7] - names of the days from Sunday (optional)
11405 * monthNamesShort string[12] - abbreviated names of the months (optional)
11406 * monthNames string[12] - names of the months (optional)
11407 * @return string - the date in the above format
11408 */
11409 formatDate: function (format, date, settings) {
11410 if (!date) {
11411 return "";
11412 }
11413
11414 var iFormat,
11415 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
11416 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
11417 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
11418 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
11419 // Check whether a format character is doubled
11420 lookAhead = function(match) {
11421 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
11422 if (matches) {
11423 iFormat++;
11424 }
11425 return matches;
11426 },
11427 // Format a number, with leading zero if necessary
11428 formatNumber = function(match, value, len) {
11429 var num = "" + value;
11430 if (lookAhead(match)) {
11431 while (num.length < len) {
11432 num = "0" + num;
11433 }
11434 }
11435 return num;
11436 },
11437 // Format a name, short or long as requested
11438 formatName = function(match, value, shortNames, longNames) {
11439 return (lookAhead(match) ? longNames[value] : shortNames[value]);
11440 },
11441 output = "",
11442 literal = false;
11443
11444 if (date) {
11445 for (iFormat = 0; iFormat < format.length; iFormat++) {
11446 if (literal) {
11447 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
11448 literal = false;
11449 } else {
11450 output += format.charAt(iFormat);
11451 }
11452 } else {
11453 switch (format.charAt(iFormat)) {
11454 case "d":
11455 output += formatNumber("d", date.getDate(), 2);
11456 break;
11457 case "D":
11458 output += formatName("D", date.getDay(), dayNamesShort, dayNames);
11459 break;
11460 case "o":
11461 output += formatNumber("o",
11462 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
11463 break;
11464 case "m":
11465 output += formatNumber("m", date.getMonth() + 1, 2);
11466 break;
11467 case "M":
11468 output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
11469 break;
11470 case "y":
11471 output += (lookAhead("y") ? date.getFullYear() :
11472 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
11473 break;
11474 case "@":
11475 output += date.getTime();
11476 break;
11477 case "!":
11478 output += date.getTime() * 10000 + this._ticksTo1970;
11479 break;
11480 case "'":
11481 if (lookAhead("'")) {
11482 output += "'";
11483 } else {
11484 literal = true;
11485 }
11486 break;
11487 default:
11488 output += format.charAt(iFormat);
11489 }
11490 }
11491 }
11492 }
11493 return output;
11494 },
11495
11496 /* Extract all possible characters from the date format. */
11497 _possibleChars: function (format) {
11498 var iFormat,
11499 chars = "",
11500 literal = false,
11501 // Check whether a format character is doubled
11502 lookAhead = function(match) {
11503 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
11504 if (matches) {
11505 iFormat++;
11506 }
11507 return matches;
11508 };
11509
11510 for (iFormat = 0; iFormat < format.length; iFormat++) {
11511 if (literal) {
11512 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
11513 literal = false;
11514 } else {
11515 chars += format.charAt(iFormat);
11516 }
11517 } else {
11518 switch (format.charAt(iFormat)) {
11519 case "d": case "m": case "y": case "@":
11520 chars += "0123456789";
11521 break;
11522 case "D": case "M":
11523 return null; // Accept anything
11524 case "'":
11525 if (lookAhead("'")) {
11526 chars += "'";
11527 } else {
11528 literal = true;
11529 }
11530 break;
11531 default:
11532 chars += format.charAt(iFormat);
11533 }
11534 }
11535 }
11536 return chars;
11537 },
11538
11539 /* Get a setting value, defaulting if necessary. */
11540 _get: function(inst, name) {
11541 return inst.settings[name] !== undefined ?
11542 inst.settings[name] : this._defaults[name];
11543 },
11544
11545 /* Parse existing date and initialise date picker. */
11546 _setDateFromField: function(inst, noDefault) {
11547 if (inst.input.val() === inst.lastVal) {
11548 return;
11549 }
11550
11551 var dateFormat = this._get(inst, "dateFormat"),
11552 dates = inst.lastVal = inst.input ? inst.input.val() : null,
11553 defaultDate = this._getDefaultDate(inst),
11554 date = defaultDate,
11555 settings = this._getFormatConfig(inst);
11556
11557 try {
11558 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
11559 } catch (event) {
11560 dates = (noDefault ? "" : dates);
11561 }
11562 inst.selectedDay = date.getDate();
11563 inst.drawMonth = inst.selectedMonth = date.getMonth();
11564 inst.drawYear = inst.selectedYear = date.getFullYear();
11565 inst.currentDay = (dates ? date.getDate() : 0);
11566 inst.currentMonth = (dates ? date.getMonth() : 0);
11567 inst.currentYear = (dates ? date.getFullYear() : 0);
11568 this._adjustInstDate(inst);
11569 },
11570
11571 /* Retrieve the default date shown on opening. */
11572 _getDefaultDate: function(inst) {
11573 return this._restrictMinMax(inst,
11574 this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
11575 },
11576
11577 /* A date may be specified as an exact value or a relative one. */
11578 _determineDate: function(inst, date, defaultDate) {
11579 var offsetNumeric = function(offset) {
11580 var date = new Date();
11581 date.setDate(date.getDate() + offset);
11582 return date;
11583 },
11584 offsetString = function(offset) {
11585 try {
11586 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
11587 offset, $.datepicker._getFormatConfig(inst));
11588 }
11589 catch (e) {
11590 // Ignore
11591 }
11592
11593 var date = (offset.toLowerCase().match(/^c/) ?
11594 $.datepicker._getDate(inst) : null) || new Date(),
11595 year = date.getFullYear(),
11596 month = date.getMonth(),
11597 day = date.getDate(),
11598 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
11599 matches = pattern.exec(offset);
11600
11601 while (matches) {
11602 switch (matches[2] || "d") {
11603 case "d" : case "D" :
11604 day += parseInt(matches[1],10); break;
11605 case "w" : case "W" :
11606 day += parseInt(matches[1],10) * 7; break;
11607 case "m" : case "M" :
11608 month += parseInt(matches[1],10);
11609 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
11610 break;
11611 case "y": case "Y" :
11612 year += parseInt(matches[1],10);
11613 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
11614 break;
11615 }
11616 matches = pattern.exec(offset);
11617 }
11618 return new Date(year, month, day);
11619 },
11620 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
11621 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
11622
11623 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
11624 if (newDate) {
11625 newDate.setHours(0);
11626 newDate.setMinutes(0);
11627 newDate.setSeconds(0);
11628 newDate.setMilliseconds(0);
11629 }
11630 return this._daylightSavingAdjust(newDate);
11631 },
11632
11633 /* Handle switch to/from daylight saving.
11634 * Hours may be non-zero on daylight saving cut-over:
11635 * > 12 when midnight changeover, but then cannot generate
11636 * midnight datetime, so jump to 1AM, otherwise reset.
11637 * @param date (Date) the date to check
11638 * @return (Date) the corrected date
11639 */
11640 _daylightSavingAdjust: function(date) {
11641 if (!date) {
11642 return null;
11643 }
11644 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
11645 return date;
11646 },
11647
11648 /* Set the date(s) directly. */
11649 _setDate: function(inst, date, noChange) {
11650 var clear = !date,
11651 origMonth = inst.selectedMonth,
11652 origYear = inst.selectedYear,
11653 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
11654
11655 inst.selectedDay = inst.currentDay = newDate.getDate();
11656 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
11657 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
11658 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
11659 this._notifyChange(inst);
11660 }
11661 this._adjustInstDate(inst);
11662 if (inst.input) {
11663 inst.input.val(clear ? "" : this._formatDate(inst));
11664 }
11665 },
11666
11667 /* Retrieve the date(s) directly. */
11668 _getDate: function(inst) {
11669 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
11670 this._daylightSavingAdjust(new Date(
11671 inst.currentYear, inst.currentMonth, inst.currentDay)));
11672 return startDate;
11673 },
11674
11675 /* Attach the onxxx handlers. These are declared statically so
11676 * they work with static code transformers like Caja.
11677 */
11678 _attachHandlers: function(inst) {
11679 var stepMonths = this._get(inst, "stepMonths"),
11680 id = "#" + inst.id.replace( /\\\\/g, "\\" );
11681 inst.dpDiv.find("[data-handler]").map(function () {
11682 var handler = {
11683 prev: function () {
11684 $.datepicker._adjustDate(id, -stepMonths, "M");
11685 },
11686 next: function () {
11687 $.datepicker._adjustDate(id, +stepMonths, "M");
11688 },
11689 hide: function () {
11690 $.datepicker._hideDatepicker();
11691 },
11692 today: function () {
11693 $.datepicker._gotoToday(id);
11694 },
11695 selectDay: function () {
11696 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
11697 return false;
11698 },
11699 selectMonth: function () {
11700 $.datepicker._selectMonthYear(id, this, "M");
11701 return false;
11702 },
11703 selectYear: function () {
11704 $.datepicker._selectMonthYear(id, this, "Y");
11705 return false;
11706 }
11707 };
11708 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
11709 });
11710 },
11711
11712 /* Generate the HTML for the current state of the date picker. */
11713 _generateHTML: function(inst) {
11714 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
11715 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
11716 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
11717 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
11718 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
11719 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
11720 tempDate = new Date(),
11721 today = this._daylightSavingAdjust(
11722 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
11723 isRTL = this._get(inst, "isRTL"),
11724 showButtonPanel = this._get(inst, "showButtonPanel"),
11725 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
11726 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
11727 numMonths = this._getNumberOfMonths(inst),
11728 showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
11729 stepMonths = this._get(inst, "stepMonths"),
11730 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
11731 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
11732 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
11733 minDate = this._getMinMaxDate(inst, "min"),
11734 maxDate = this._getMinMaxDate(inst, "max"),
11735 drawMonth = inst.drawMonth - showCurrentAtPos,
11736 drawYear = inst.drawYear;
11737
11738 if (drawMonth < 0) {
11739 drawMonth += 12;
11740 drawYear--;
11741 }
11742 if (maxDate) {
11743 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
11744 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
11745 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
11746 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
11747 drawMonth--;
11748 if (drawMonth < 0) {
11749 drawMonth = 11;
11750 drawYear--;
11751 }
11752 }
11753 }
11754 inst.drawMonth = drawMonth;
11755 inst.drawYear = drawYear;
11756
11757 prevText = this._get(inst, "prevText");
11758 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
11759 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
11760 this._getFormatConfig(inst)));
11761
11762 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
11763 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
11764 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
11765 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
11766
11767 nextText = this._get(inst, "nextText");
11768 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
11769 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
11770 this._getFormatConfig(inst)));
11771
11772 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
11773 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
11774 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
11775 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
11776
11777 currentText = this._get(inst, "currentText");
11778 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
11779 currentText = (!navigationAsDateFormat ? currentText :
11780 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
11781
11782 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
11783 this._get(inst, "closeText") + "</button>" : "");
11784
11785 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
11786 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
11787 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
11788
11789 firstDay = parseInt(this._get(inst, "firstDay"),10);
11790 firstDay = (isNaN(firstDay) ? 0 : firstDay);
11791
11792 showWeek = this._get(inst, "showWeek");
11793 dayNames = this._get(inst, "dayNames");
11794 dayNamesMin = this._get(inst, "dayNamesMin");
11795 monthNames = this._get(inst, "monthNames");
11796 monthNamesShort = this._get(inst, "monthNamesShort");
11797 beforeShowDay = this._get(inst, "beforeShowDay");
11798 showOtherMonths = this._get(inst, "showOtherMonths");
11799 selectOtherMonths = this._get(inst, "selectOtherMonths");
11800 defaultDate = this._getDefaultDate(inst);
11801 html = "";
11802 dow;
11803 for (row = 0; row < numMonths[0]; row++) {
11804 group = "";
11805 this.maxRows = 4;
11806 for (col = 0; col < numMonths[1]; col++) {
11807 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
11808 cornerClass = " ui-corner-all";
11809 calender = "";
11810 if (isMultiMonth) {
11811 calender += "<div class='ui-datepicker-group";
11812 if (numMonths[1] > 1) {
11813 switch (col) {
11814 case 0: calender += " ui-datepicker-group-first";
11815 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
11816 case numMonths[1]-1: calender += " ui-datepicker-group-last";
11817 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
11818 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
11819 }
11820 }
11821 calender += "'>";
11822 }
11823 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
11824 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
11825 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
11826 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
11827 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
11828 "</div><table class='ui-datepicker-calendar'><thead>" +
11829 "<tr>";
11830 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
11831 for (dow = 0; dow < 7; dow++) { // days of the week
11832 day = (dow + firstDay) % 7;
11833 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
11834 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
11835 }
11836 calender += thead + "</tr></thead><tbody>";
11837 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
11838 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
11839 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
11840 }
11841 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
11842 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
11843 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
11844 this.maxRows = numRows;
11845 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
11846 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
11847 calender += "<tr>";
11848 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
11849 this._get(inst, "calculateWeek")(printDate) + "</td>");
11850 for (dow = 0; dow < 7; dow++) { // create date picker days
11851 daySettings = (beforeShowDay ?
11852 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
11853 otherMonth = (printDate.getMonth() !== drawMonth);
11854 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
11855 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
11856 tbody += "<td class='" +
11857 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
11858 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
11859 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
11860 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
11861 // or defaultDate is current printedDate and defaultDate is selectedDate
11862 " " + this._dayOverClass : "") + // highlight selected day
11863 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
11864 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
11865 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
11866 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
11867 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
11868 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
11869 (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
11870 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
11871 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
11872 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
11873 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
11874 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
11875 printDate.setDate(printDate.getDate() + 1);
11876 printDate = this._daylightSavingAdjust(printDate);
11877 }
11878 calender += tbody + "</tr>";
11879 }
11880 drawMonth++;
11881 if (drawMonth > 11) {
11882 drawMonth = 0;
11883 drawYear++;
11884 }
11885 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
11886 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
11887 group += calender;
11888 }
11889 html += group;
11890 }
11891 html += buttonPanel;
11892 inst._keyEvent = false;
11893 return html;
11894 },
11895
11896 /* Generate the month and year header. */
11897 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
11898 secondary, monthNames, monthNamesShort) {
11899
11900 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
11901 changeMonth = this._get(inst, "changeMonth"),
11902 changeYear = this._get(inst, "changeYear"),
11903 showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
11904 html = "<div class='ui-datepicker-title'>",
11905 monthHtml = "";
11906
11907 // month selection
11908 if (secondary || !changeMonth) {
11909 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
11910 } else {
11911 inMinYear = (minDate && minDate.getFullYear() === drawYear);
11912 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
11913 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
11914 for ( month = 0; month < 12; month++) {
11915 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
11916 monthHtml += "<option value='" + month + "'" +
11917 (month === drawMonth ? " selected='selected'" : "") +
11918 ">" + monthNamesShort[month] + "</option>";
11919 }
11920 }
11921 monthHtml += "</select>";
11922 }
11923
11924 if (!showMonthAfterYear) {
11925 html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
11926 }
11927
11928 // year selection
11929 if ( !inst.yearshtml ) {
11930 inst.yearshtml = "";
11931 if (secondary || !changeYear) {
11932 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
11933 } else {
11934 // determine range of years to display
11935 years = this._get(inst, "yearRange").split(":");
11936 thisYear = new Date().getFullYear();
11937 determineYear = function(value) {
11938 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
11939 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
11940 parseInt(value, 10)));
11941 return (isNaN(year) ? thisYear : year);
11942 };
11943 year = determineYear(years[0]);
11944 endYear = Math.max(year, determineYear(years[1] || ""));
11945 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
11946 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
11947 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
11948 for (; year <= endYear; year++) {
11949 inst.yearshtml += "<option value='" + year + "'" +
11950 (year === drawYear ? " selected='selected'" : "") +
11951 ">" + year + "</option>";
11952 }
11953 inst.yearshtml += "</select>";
11954
11955 html += inst.yearshtml;
11956 inst.yearshtml = null;
11957 }
11958 }
11959
11960 html += this._get(inst, "yearSuffix");
11961 if (showMonthAfterYear) {
11962 html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
11963 }
11964 html += "</div>"; // Close datepicker_header
11965 return html;
11966 },
11967
11968 /* Adjust one of the date sub-fields. */
11969 _adjustInstDate: function(inst, offset, period) {
11970 var year = inst.drawYear + (period === "Y" ? offset : 0),
11971 month = inst.drawMonth + (period === "M" ? offset : 0),
11972 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
11973 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
11974
11975 inst.selectedDay = date.getDate();
11976 inst.drawMonth = inst.selectedMonth = date.getMonth();
11977 inst.drawYear = inst.selectedYear = date.getFullYear();
11978 if (period === "M" || period === "Y") {
11979 this._notifyChange(inst);
11980 }
11981 },
11982
11983 /* Ensure a date is within any min/max bounds. */
11984 _restrictMinMax: function(inst, date) {
11985 var minDate = this._getMinMaxDate(inst, "min"),
11986 maxDate = this._getMinMaxDate(inst, "max"),
11987 newDate = (minDate && date < minDate ? minDate : date);
11988 return (maxDate && newDate > maxDate ? maxDate : newDate);
11989 },
11990
11991 /* Notify change of month/year. */
11992 _notifyChange: function(inst) {
11993 var onChange = this._get(inst, "onChangeMonthYear");
11994 if (onChange) {
11995 onChange.apply((inst.input ? inst.input[0] : null),
11996 [inst.selectedYear, inst.selectedMonth + 1, inst]);
11997 }
11998 },
11999
12000 /* Determine the number of months to show. */
12001 _getNumberOfMonths: function(inst) {
12002 var numMonths = this._get(inst, "numberOfMonths");
12003 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
12004 },
12005
12006 /* Determine the current maximum date - ensure no time components are set. */
12007 _getMinMaxDate: function(inst, minMax) {
12008 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
12009 },
12010
12011 /* Find the number of days in a given month. */
12012 _getDaysInMonth: function(year, month) {
12013 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
12014 },
12015
12016 /* Find the day of the week of the first of a month. */
12017 _getFirstDayOfMonth: function(year, month) {
12018 return new Date(year, month, 1).getDay();
12019 },
12020
12021 /* Determines if we should allow a "next/prev" month display change. */
12022 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
12023 var numMonths = this._getNumberOfMonths(inst),
12024 date = this._daylightSavingAdjust(new Date(curYear,
12025 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
12026
12027 if (offset < 0) {
12028 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
12029 }
12030 return this._isInRange(inst, date);
12031 },
12032
12033 /* Is the given date in the accepted range? */
12034 _isInRange: function(inst, date) {
12035 var yearSplit, currentYear,
12036 minDate = this._getMinMaxDate(inst, "min"),
12037 maxDate = this._getMinMaxDate(inst, "max"),
12038 minYear = null,
12039 maxYear = null,
12040 years = this._get(inst, "yearRange");
12041 if (years){
12042 yearSplit = years.split(":");
12043 currentYear = new Date().getFullYear();
12044 minYear = parseInt(yearSplit[0], 10);
12045 maxYear = parseInt(yearSplit[1], 10);
12046 if ( yearSplit[0].match(/[+\-].*/) ) {
12047 minYear += currentYear;
12048 }
12049 if ( yearSplit[1].match(/[+\-].*/) ) {
12050 maxYear += currentYear;
12051 }
12052 }
12053
12054 return ((!minDate || date.getTime() >= minDate.getTime()) &&
12055 (!maxDate || date.getTime() <= maxDate.getTime()) &&
12056 (!minYear || date.getFullYear() >= minYear) &&
12057 (!maxYear || date.getFullYear() <= maxYear));
12058 },
12059
12060 /* Provide the configuration settings for formatting/parsing. */
12061 _getFormatConfig: function(inst) {
12062 var shortYearCutoff = this._get(inst, "shortYearCutoff");
12063 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
12064 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
12065 return {shortYearCutoff: shortYearCutoff,
12066 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
12067 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
12068 },
12069
12070 /* Format the given date for display. */
12071 _formatDate: function(inst, day, month, year) {
12072 if (!day) {
12073 inst.currentDay = inst.selectedDay;
12074 inst.currentMonth = inst.selectedMonth;
12075 inst.currentYear = inst.selectedYear;
12076 }
12077 var date = (day ? (typeof day === "object" ? day :
12078 this._daylightSavingAdjust(new Date(year, month, day))) :
12079 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
12080 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
12081 }
12082 });
12083
12084 /*
12085 * Bind hover events for datepicker elements.
12086 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
12087 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
12088 */
12089 function bindHover(dpDiv) {
12090 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
12091 return dpDiv.delegate(selector, "mouseout", function() {
12092 $(this).removeClass("ui-state-hover");
12093 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
12094 $(this).removeClass("ui-datepicker-prev-hover");
12095 }
12096 if (this.className.indexOf("ui-datepicker-next") !== -1) {
12097 $(this).removeClass("ui-datepicker-next-hover");
12098 }
12099 })
12100 .delegate(selector, "mouseover", function(){
12101 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
12102 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
12103 $(this).addClass("ui-state-hover");
12104 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
12105 $(this).addClass("ui-datepicker-prev-hover");
12106 }
12107 if (this.className.indexOf("ui-datepicker-next") !== -1) {
12108 $(this).addClass("ui-datepicker-next-hover");
12109 }
12110 }
12111 });
12112 }
12113
12114 /* jQuery extend now ignores nulls! */
12115 function extendRemove(target, props) {
12116 $.extend(target, props);
12117 for (var name in props) {
12118 if (props[name] == null) {
12119 target[name] = props[name];
12120 }
12121 }
12122 return target;
12123 }
12124
12125 /* Invoke the datepicker functionality.
12126 @param options string - a command, optionally followed by additional parameters or
12127 Object - settings for attaching new datepicker functionality
12128 @return jQuery object */
12129 $.fn.datepicker = function(options){
12130
12131 /* Verify an empty collection wasn't passed - Fixes #6976 */
12132 if ( !this.length ) {
12133 return this;
12134 }
12135
12136 /* Initialise the date picker. */
12137 if (!$.datepicker.initialized) {
12138 $(document).mousedown($.datepicker._checkExternalClick);
12139 $.datepicker.initialized = true;
12140 }
12141
12142 /* Append datepicker main container to body if not exist. */
12143 if ($("#"+$.datepicker._mainDivId).length === 0) {
12144 $("body").append($.datepicker.dpDiv);
12145 }
12146
12147 var otherArgs = Array.prototype.slice.call(arguments, 1);
12148 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
12149 return $.datepicker["_" + options + "Datepicker"].
12150 apply($.datepicker, [this[0]].concat(otherArgs));
12151 }
12152 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
12153 return $.datepicker["_" + options + "Datepicker"].
12154 apply($.datepicker, [this[0]].concat(otherArgs));
12155 }
12156 return this.each(function() {
12157 typeof options === "string" ?
12158 $.datepicker["_" + options + "Datepicker"].
12159 apply($.datepicker, [this].concat(otherArgs)) :
12160 $.datepicker._attachDatepicker(this, options);
12161 });
12162 };
12163
12164 $.datepicker = new Datepicker(); // singleton instance
12165 $.datepicker.initialized = false;
12166 $.datepicker.uuid = new Date().getTime();
12167 $.datepicker.version = "1.10.3";
12168
12169 })(jQuery);
12170 (function( $, undefined ) {
12171
12172 var sizeRelatedOptions = {
12173 buttons: true,
12174 height: true,
12175 maxHeight: true,
12176 maxWidth: true,
12177 minHeight: true,
12178 minWidth: true,
12179 width: true
12180 },
12181 resizableRelatedOptions = {
12182 maxHeight: true,
12183 maxWidth: true,
12184 minHeight: true,
12185 minWidth: true
12186 };
12187
12188 $.widget( "ui.dialog", {
12189 version: "1.10.3",
12190 options: {
12191 appendTo: "body",
12192 autoOpen: true,
12193 buttons: [],
12194 closeOnEscape: true,
12195 closeText: "close",
12196 dialogClass: "",
12197 draggable: true,
12198 hide: null,
12199 height: "auto",
12200 maxHeight: null,
12201 maxWidth: null,
12202 minHeight: 150,
12203 minWidth: 150,
12204 modal: false,
12205 position: {
12206 my: "center",
12207 at: "center",
12208 of: window,
12209 collision: "fit",
12210 // Ensure the titlebar is always visible
12211 using: function( pos ) {
12212 var topOffset = $( this ).css( pos ).offset().top;
12213 if ( topOffset < 0 ) {
12214 $( this ).css( "top", pos.top - topOffset );
12215 }
12216 }
12217 },
12218 resizable: true,
12219 show: null,
12220 title: null,
12221 width: 300,
12222
12223 // callbacks
12224 beforeClose: null,
12225 close: null,
12226 drag: null,
12227 dragStart: null,
12228 dragStop: null,
12229 focus: null,
12230 open: null,
12231 resize: null,
12232 resizeStart: null,
12233 resizeStop: null
12234 },
12235
12236 _create: function() {
12237 this.originalCss = {
12238 display: this.element[0].style.display,
12239 width: this.element[0].style.width,
12240 minHeight: this.element[0].style.minHeight,
12241 maxHeight: this.element[0].style.maxHeight,
12242 height: this.element[0].style.height
12243 };
12244 this.originalPosition = {
12245 parent: this.element.parent(),
12246 index: this.element.parent().children().index( this.element )
12247 };
12248 this.originalTitle = this.element.attr("title");
12249 this.options.title = this.options.title || this.originalTitle;
12250
12251 this._createWrapper();
12252
12253 this.element
12254 .show()
12255 .removeAttr("title")
12256 .addClass("ui-dialog-content ui-widget-content")
12257 .appendTo( this.uiDialog );
12258
12259 this._createTitlebar();
12260 this._createButtonPane();
12261
12262 if ( this.options.draggable && $.fn.draggable ) {
12263 this._makeDraggable();
12264 }
12265 if ( this.options.resizable && $.fn.resizable ) {
12266 this._makeResizable();
12267 }
12268
12269 this._isOpen = false;
12270 },
12271
12272 _init: function() {
12273 if ( this.options.autoOpen ) {
12274 this.open();
12275 }
12276 },
12277
12278 _appendTo: function() {
12279 var element = this.options.appendTo;
12280 if ( element && (element.jquery || element.nodeType) ) {
12281 return $( element );
12282 }
12283 return this.document.find( element || "body" ).eq( 0 );
12284 },
12285
12286 _destroy: function() {
12287 var next,
12288 originalPosition = this.originalPosition;
12289
12290 this._destroyOverlay();
12291
12292 this.element
12293 .removeUniqueId()
12294 .removeClass("ui-dialog-content ui-widget-content")
12295 .css( this.originalCss )
12296 // Without detaching first, the following becomes really slow
12297 .detach();
12298
12299 this.uiDialog.stop( true, true ).remove();
12300
12301 if ( this.originalTitle ) {
12302 this.element.attr( "title", this.originalTitle );
12303 }
12304
12305 next = originalPosition.parent.children().eq( originalPosition.index );
12306 // Don't try to place the dialog next to itself (#8613)
12307 if ( next.length && next[0] !== this.element[0] ) {
12308 next.before( this.element );
12309 } else {
12310 originalPosition.parent.append( this.element );
12311 }
12312 },
12313
12314 widget: function() {
12315 return this.uiDialog;
12316 },
12317
12318 disable: $.noop,
12319 enable: $.noop,
12320
12321 close: function( event ) {
12322 var that = this;
12323
12324 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12325 return;
12326 }
12327
12328 this._isOpen = false;
12329 this._destroyOverlay();
12330
12331 if ( !this.opener.filter(":focusable").focus().length ) {
12332 // Hiding a focused element doesn't trigger blur in WebKit
12333 // so in case we have nothing to focus on, explicitly blur the active element
12334 // https://bugs.webkit.org/show_bug.cgi?id=47182
12335 $( this.document[0].activeElement ).blur();
12336 }
12337
12338 this._hide( this.uiDialog, this.options.hide, function() {
12339 that._trigger( "close", event );
12340 });
12341 },
12342
12343 isOpen: function() {
12344 return this._isOpen;
12345 },
12346
12347 moveToTop: function() {
12348 this._moveToTop();
12349 },
12350
12351 _moveToTop: function( event, silent ) {
12352 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
12353 if ( moved && !silent ) {
12354 this._trigger( "focus", event );
12355 }
12356 return moved;
12357 },
12358
12359 open: function() {
12360 var that = this;
12361 if ( this._isOpen ) {
12362 if ( this._moveToTop() ) {
12363 this._focusTabbable();
12364 }
12365 return;
12366 }
12367
12368 this._isOpen = true;
12369 this.opener = $( this.document[0].activeElement );
12370
12371 this._size();
12372 this._position();
12373 this._createOverlay();
12374 this._moveToTop( null, true );
12375 this._show( this.uiDialog, this.options.show, function() {
12376 that._focusTabbable();
12377 that._trigger("focus");
12378 });
12379
12380 this._trigger("open");
12381 },
12382
12383 _focusTabbable: function() {
12384 // Set focus to the first match:
12385 // 1. First element inside the dialog matching [autofocus]
12386 // 2. Tabbable element inside the content element
12387 // 3. Tabbable element inside the buttonpane
12388 // 4. The close button
12389 // 5. The dialog itself
12390 var hasFocus = this.element.find("[autofocus]");
12391 if ( !hasFocus.length ) {
12392 hasFocus = this.element.find(":tabbable");
12393 }
12394 if ( !hasFocus.length ) {
12395 hasFocus = this.uiDialogButtonPane.find(":tabbable");
12396 }
12397 if ( !hasFocus.length ) {
12398 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
12399 }
12400 if ( !hasFocus.length ) {
12401 hasFocus = this.uiDialog;
12402 }
12403 hasFocus.eq( 0 ).focus();
12404 },
12405
12406 _keepFocus: function( event ) {
12407 function checkFocus() {
12408 var activeElement = this.document[0].activeElement,
12409 isActive = this.uiDialog[0] === activeElement ||
12410 $.contains( this.uiDialog[0], activeElement );
12411 if ( !isActive ) {
12412 this._focusTabbable();
12413 }
12414 }
12415 event.preventDefault();
12416 checkFocus.call( this );
12417 // support: IE
12418 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
12419 // so we check again later
12420 this._delay( checkFocus );
12421 },
12422
12423 _createWrapper: function() {
12424 this.uiDialog = $("<div>")
12425 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
12426 this.options.dialogClass )
12427 .hide()
12428 .attr({
12429 // Setting tabIndex makes the div focusable
12430 tabIndex: -1,
12431 role: "dialog"
12432 })
12433 .appendTo( this._appendTo() );
12434
12435 this._on( this.uiDialog, {
12436 keydown: function( event ) {
12437 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12438 event.keyCode === $.ui.keyCode.ESCAPE ) {
12439 event.preventDefault();
12440 this.close( event );
12441 return;
12442 }
12443
12444 // prevent tabbing out of dialogs
12445 if ( event.keyCode !== $.ui.keyCode.TAB ) {
12446 return;
12447 }
12448 var tabbables = this.uiDialog.find(":tabbable"),
12449 first = tabbables.filter(":first"),
12450 last = tabbables.filter(":last");
12451
12452 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
12453 first.focus( 1 );
12454 event.preventDefault();
12455 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
12456 last.focus( 1 );
12457 event.preventDefault();
12458 }
12459 },
12460 mousedown: function( event ) {
12461 if ( this._moveToTop( event ) ) {
12462 this._focusTabbable();
12463 }
12464 }
12465 });
12466
12467 // We assume that any existing aria-describedby attribute means
12468 // that the dialog content is marked up properly
12469 // otherwise we brute force the content as the description
12470 if ( !this.element.find("[aria-describedby]").length ) {
12471 this.uiDialog.attr({
12472 "aria-describedby": this.element.uniqueId().attr("id")
12473 });
12474 }
12475 },
12476
12477 _createTitlebar: function() {
12478 var uiDialogTitle;
12479
12480 this.uiDialogTitlebar = $("<div>")
12481 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
12482 .prependTo( this.uiDialog );
12483 this._on( this.uiDialogTitlebar, {
12484 mousedown: function( event ) {
12485 // Don't prevent click on close button (#8838)
12486 // Focusing a dialog that is partially scrolled out of view
12487 // causes the browser to scroll it into view, preventing the click event
12488 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
12489 // Dialog isn't getting focus when dragging (#8063)
12490 this.uiDialog.focus();
12491 }
12492 }
12493 });
12494
12495 this.uiDialogTitlebarClose = $("<button></button>")
12496 .button({
12497 label: this.options.closeText,
12498 icons: {
12499 primary: "ui-icon-closethick"
12500 },
12501 text: false
12502 })
12503 .addClass("ui-dialog-titlebar-close")
12504 .appendTo( this.uiDialogTitlebar );
12505 this._on( this.uiDialogTitlebarClose, {
12506 click: function( event ) {
12507 event.preventDefault();
12508 this.close( event );
12509 }
12510 });
12511
12512 uiDialogTitle = $("<span>")
12513 .uniqueId()
12514 .addClass("ui-dialog-title")
12515 .prependTo( this.uiDialogTitlebar );
12516 this._title( uiDialogTitle );
12517
12518 this.uiDialog.attr({
12519 "aria-labelledby": uiDialogTitle.attr("id")
12520 });
12521 },
12522
12523 _title: function( title ) {
12524 if ( !this.options.title ) {
12525 title.html("&#160;");
12526 }
12527 title.text( this.options.title );
12528 },
12529
12530 _createButtonPane: function() {
12531 this.uiDialogButtonPane = $("<div>")
12532 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
12533
12534 this.uiButtonSet = $("<div>")
12535 .addClass("ui-dialog-buttonset")
12536 .appendTo( this.uiDialogButtonPane );
12537
12538 this._createButtons();
12539 },
12540
12541 _createButtons: function() {
12542 var that = this,
12543 buttons = this.options.buttons;
12544
12545 // if we already have a button pane, remove it
12546 this.uiDialogButtonPane.remove();
12547 this.uiButtonSet.empty();
12548
12549 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
12550 this.uiDialog.removeClass("ui-dialog-buttons");
12551 return;
12552 }
12553
12554 $.each( buttons, function( name, props ) {
12555 var click, buttonOptions;
12556 props = $.isFunction( props ) ?
12557 { click: props, text: name } :
12558 props;
12559 // Default to a non-submitting button
12560 props = $.extend( { type: "button" }, props );
12561 // Change the context for the click callback to be the main element
12562 click = props.click;
12563 props.click = function() {
12564 click.apply( that.element[0], arguments );
12565 };
12566 buttonOptions = {
12567 icons: props.icons,
12568 text: props.showText
12569 };
12570 delete props.icons;
12571 delete props.showText;
12572 $( "<button></button>", props )
12573 .button( buttonOptions )
12574 .appendTo( that.uiButtonSet );
12575 });
12576 this.uiDialog.addClass("ui-dialog-buttons");
12577 this.uiDialogButtonPane.appendTo( this.uiDialog );
12578 },
12579
12580 _makeDraggable: function() {
12581 var that = this,
12582 options = this.options;
12583
12584 function filteredUi( ui ) {
12585 return {
12586 position: ui.position,
12587 offset: ui.offset
12588 };
12589 }
12590
12591 this.uiDialog.draggable({
12592 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12593 handle: ".ui-dialog-titlebar",
12594 containment: "document",
12595 start: function( event, ui ) {
12596 $( this ).addClass("ui-dialog-dragging");
12597 that._blockFrames();
12598 that._trigger( "dragStart", event, filteredUi( ui ) );
12599 },
12600 drag: function( event, ui ) {
12601 that._trigger( "drag", event, filteredUi( ui ) );
12602 },
12603 stop: function( event, ui ) {
12604 options.position = [
12605 ui.position.left - that.document.scrollLeft(),
12606 ui.position.top - that.document.scrollTop()
12607 ];
12608 $( this ).removeClass("ui-dialog-dragging");
12609 that._unblockFrames();
12610 that._trigger( "dragStop", event, filteredUi( ui ) );
12611 }
12612 });
12613 },
12614
12615 _makeResizable: function() {
12616 var that = this,
12617 options = this.options,
12618 handles = options.resizable,
12619 // .ui-resizable has position: relative defined in the stylesheet
12620 // but dialogs have to use absolute or fixed positioning
12621 position = this.uiDialog.css("position"),
12622 resizeHandles = typeof handles === "string" ?
12623 handles :
12624 "n,e,s,w,se,sw,ne,nw";
12625
12626 function filteredUi( ui ) {
12627 return {
12628 originalPosition: ui.originalPosition,
12629 originalSize: ui.originalSize,
12630 position: ui.position,
12631 size: ui.size
12632 };
12633 }
12634
12635 this.uiDialog.resizable({
12636 cancel: ".ui-dialog-content",
12637 containment: "document",
12638 alsoResize: this.element,
12639 maxWidth: options.maxWidth,
12640 maxHeight: options.maxHeight,
12641 minWidth: options.minWidth,
12642 minHeight: this._minHeight(),
12643 handles: resizeHandles,
12644 start: function( event, ui ) {
12645 $( this ).addClass("ui-dialog-resizing");
12646 that._blockFrames();
12647 that._trigger( "resizeStart", event, filteredUi( ui ) );
12648 },
12649 resize: function( event, ui ) {
12650 that._trigger( "resize", event, filteredUi( ui ) );
12651 },
12652 stop: function( event, ui ) {
12653 options.height = $( this ).height();
12654 options.width = $( this ).width();
12655 $( this ).removeClass("ui-dialog-resizing");
12656 that._unblockFrames();
12657 that._trigger( "resizeStop", event, filteredUi( ui ) );
12658 }
12659 })
12660 .css( "position", position );
12661 },
12662
12663 _minHeight: function() {
12664 var options = this.options;
12665
12666 return options.height === "auto" ?
12667 options.minHeight :
12668 Math.min( options.minHeight, options.height );
12669 },
12670
12671 _position: function() {
12672 // Need to show the dialog to get the actual offset in the position plugin
12673 var isVisible = this.uiDialog.is(":visible");
12674 if ( !isVisible ) {
12675 this.uiDialog.show();
12676 }
12677 this.uiDialog.position( this.options.position );
12678 if ( !isVisible ) {
12679 this.uiDialog.hide();
12680 }
12681 },
12682
12683 _setOptions: function( options ) {
12684 var that = this,
12685 resize = false,
12686 resizableOptions = {};
12687
12688 $.each( options, function( key, value ) {
12689 that._setOption( key, value );
12690
12691 if ( key in sizeRelatedOptions ) {
12692 resize = true;
12693 }
12694 if ( key in resizableRelatedOptions ) {
12695 resizableOptions[ key ] = value;
12696 }
12697 });
12698
12699 if ( resize ) {
12700 this._size();
12701 this._position();
12702 }
12703 if ( this.uiDialog.is(":data(ui-resizable)") ) {
12704 this.uiDialog.resizable( "option", resizableOptions );
12705 }
12706 },
12707
12708 _setOption: function( key, value ) {
12709 /*jshint maxcomplexity:15*/
12710 var isDraggable, isResizable,
12711 uiDialog = this.uiDialog;
12712
12713 if ( key === "dialogClass" ) {
12714 uiDialog
12715 .removeClass( this.options.dialogClass )
12716 .addClass( value );
12717 }
12718
12719 if ( key === "disabled" ) {
12720 return;
12721 }
12722
12723 this._super( key, value );
12724
12725 if ( key === "appendTo" ) {
12726 this.uiDialog.appendTo( this._appendTo() );
12727 }
12728
12729 if ( key === "buttons" ) {
12730 this._createButtons();
12731 }
12732
12733 if ( key === "closeText" ) {
12734 this.uiDialogTitlebarClose.button({
12735 // Ensure that we always pass a string
12736 label: "" + value
12737 });
12738 }
12739
12740 if ( key === "draggable" ) {
12741 isDraggable = uiDialog.is(":data(ui-draggable)");
12742 if ( isDraggable && !value ) {
12743 uiDialog.draggable("destroy");
12744 }
12745
12746 if ( !isDraggable && value ) {
12747 this._makeDraggable();
12748 }
12749 }
12750
12751 if ( key === "position" ) {
12752 this._position();
12753 }
12754
12755 if ( key === "resizable" ) {
12756 // currently resizable, becoming non-resizable
12757 isResizable = uiDialog.is(":data(ui-resizable)");
12758 if ( isResizable && !value ) {
12759 uiDialog.resizable("destroy");
12760 }
12761
12762 // currently resizable, changing handles
12763 if ( isResizable && typeof value === "string" ) {
12764 uiDialog.resizable( "option", "handles", value );
12765 }
12766
12767 // currently non-resizable, becoming resizable
12768 if ( !isResizable && value !== false ) {
12769 this._makeResizable();
12770 }
12771 }
12772
12773 if ( key === "title" ) {
12774 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
12775 }
12776 },
12777
12778 _size: function() {
12779 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12780 // divs will both have width and height set, so we need to reset them
12781 var nonContentHeight, minContentHeight, maxContentHeight,
12782 options = this.options;
12783
12784 // Reset content sizing
12785 this.element.show().css({
12786 width: "auto",
12787 minHeight: 0,
12788 maxHeight: "none",
12789 height: 0
12790 });
12791
12792 if ( options.minWidth > options.width ) {
12793 options.width = options.minWidth;
12794 }
12795
12796 // reset wrapper sizing
12797 // determine the height of all the non-content elements
12798 nonContentHeight = this.uiDialog.css({
12799 height: "auto",
12800 width: options.width
12801 })
12802 .outerHeight();
12803 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12804 maxContentHeight = typeof options.maxHeight === "number" ?
12805 Math.max( 0, options.maxHeight - nonContentHeight ) :
12806 "none";
12807
12808 if ( options.height === "auto" ) {
12809 this.element.css({
12810 minHeight: minContentHeight,
12811 maxHeight: maxContentHeight,
12812 height: "auto"
12813 });
12814 } else {
12815 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12816 }
12817
12818 if (this.uiDialog.is(":data(ui-resizable)") ) {
12819 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12820 }
12821 },
12822
12823 _blockFrames: function() {
12824 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
12825 var iframe = $( this );
12826
12827 return $( "<div>" )
12828 .css({
12829 position: "absolute",
12830 width: iframe.outerWidth(),
12831 height: iframe.outerHeight()
12832 })
12833 .appendTo( iframe.parent() )
12834 .offset( iframe.offset() )[0];
12835 });
12836 },
12837
12838 _unblockFrames: function() {
12839 if ( this.iframeBlocks ) {
12840 this.iframeBlocks.remove();
12841 delete this.iframeBlocks;
12842 }
12843 },
12844
12845 _allowInteraction: function( event ) {
12846 if ( $( event.target ).closest(".ui-dialog").length ) {
12847 return true;
12848 }
12849
12850 // TODO: Remove hack when datepicker implements
12851 // the .ui-front logic (#8989)
12852 return !!$( event.target ).closest(".ui-datepicker").length;
12853 },
12854
12855 _createOverlay: function() {
12856 if ( !this.options.modal ) {
12857 return;
12858 }
12859
12860 var that = this,
12861 widgetFullName = this.widgetFullName;
12862 if ( !$.ui.dialog.overlayInstances ) {
12863 // Prevent use of anchors and inputs.
12864 // We use a delay in case the overlay is created from an
12865 // event that we're going to be cancelling. (#2804)
12866 this._delay(function() {
12867 // Handle .dialog().dialog("close") (#4065)
12868 if ( $.ui.dialog.overlayInstances ) {
12869 this.document.bind( "focusin.dialog", function( event ) {
12870 if ( !that._allowInteraction( event ) ) {
12871 event.preventDefault();
12872 $(".ui-dialog:visible:last .ui-dialog-content")
12873 .data( widgetFullName )._focusTabbable();
12874 }
12875 });
12876 }
12877 });
12878 }
12879
12880 this.overlay = $("<div>")
12881 .addClass("ui-widget-overlay ui-front")
12882 .appendTo( this._appendTo() );
12883 this._on( this.overlay, {
12884 mousedown: "_keepFocus"
12885 });
12886 $.ui.dialog.overlayInstances++;
12887 },
12888
12889 _destroyOverlay: function() {
12890 if ( !this.options.modal ) {
12891 return;
12892 }
12893
12894 if ( this.overlay ) {
12895 $.ui.dialog.overlayInstances--;
12896
12897 if ( !$.ui.dialog.overlayInstances ) {
12898 this.document.unbind( "focusin.dialog" );
12899 }
12900 this.overlay.remove();
12901 this.overlay = null;
12902 }
12903 }
12904 });
12905
12906 $.ui.dialog.overlayInstances = 0;
12907
12908 // DEPRECATED
12909 if ( $.uiBackCompat !== false ) {
12910 // position option with array notation
12911 // just override with old implementation
12912 $.widget( "ui.dialog", $.ui.dialog, {
12913 _position: function() {
12914 var position = this.options.position,
12915 myAt = [],
12916 offset = [ 0, 0 ],
12917 isVisible;
12918
12919 if ( position ) {
12920 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
12921 myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
12922 if ( myAt.length === 1 ) {
12923 myAt[1] = myAt[0];
12924 }
12925
12926 $.each( [ "left", "top" ], function( i, offsetPosition ) {
12927 if ( +myAt[ i ] === myAt[ i ] ) {
12928 offset[ i ] = myAt[ i ];
12929 myAt[ i ] = offsetPosition;
12930 }
12931 });
12932
12933 position = {
12934 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
12935 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
12936 at: myAt.join(" ")
12937 };
12938 }
12939
12940 position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
12941 } else {
12942 position = $.ui.dialog.prototype.options.position;
12943 }
12944
12945 // need to show the dialog to get the actual offset in the position plugin
12946 isVisible = this.uiDialog.is(":visible");
12947 if ( !isVisible ) {
12948 this.uiDialog.show();
12949 }
12950 this.uiDialog.position( position );
12951 if ( !isVisible ) {
12952 this.uiDialog.hide();
12953 }
12954 }
12955 });
12956 }
12957
12958 }( jQuery ) );
12959 (function( $, undefined ) {
12960
12961 $.widget( "ui.menu", {
12962 version: "1.10.3",
12963 defaultElement: "<ul>",
12964 delay: 300,
12965 options: {
12966 icons: {
12967 submenu: "ui-icon-carat-1-e"
12968 },
12969 menus: "ul",
12970 position: {
12971 my: "left top",
12972 at: "right top"
12973 },
12974 role: "menu",
12975
12976 // callbacks
12977 blur: null,
12978 focus: null,
12979 select: null
12980 },
12981
12982 _create: function() {
12983 this.activeMenu = this.element;
12984 // flag used to prevent firing of the click handler
12985 // as the event bubbles up through nested menus
12986 this.mouseHandled = false;
12987 this.element
12988 .uniqueId()
12989 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
12990 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
12991 .attr({
12992 role: this.options.role,
12993 tabIndex: 0
12994 })
12995 // need to catch all clicks on disabled menu
12996 // not possible through _on
12997 .bind( "click" + this.eventNamespace, $.proxy(function( event ) {
12998 if ( this.options.disabled ) {
12999 event.preventDefault();
13000 }
13001 }, this ));
13002
13003 if ( this.options.disabled ) {
13004 this.element
13005 .addClass( "ui-state-disabled" )
13006 .attr( "aria-disabled", "true" );
13007 }
13008
13009 this._on({
13010 // Prevent focus from sticking to links inside menu after clicking
13011 // them (focus should always stay on UL during navigation).
13012 "mousedown .ui-menu-item > a": function( event ) {
13013 event.preventDefault();
13014 },
13015 "click .ui-state-disabled > a": function( event ) {
13016 event.preventDefault();
13017 },
13018 "click .ui-menu-item:has(a)": function( event ) {
13019 var target = $( event.target ).closest( ".ui-menu-item" );
13020 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
13021 this.mouseHandled = true;
13022
13023 this.select( event );
13024 // Open submenu on click
13025 if ( target.has( ".ui-menu" ).length ) {
13026 this.expand( event );
13027 } else if ( !this.element.is( ":focus" ) ) {
13028 // Redirect focus to the menu
13029 this.element.trigger( "focus", [ true ] );
13030
13031 // If the active item is on the top level, let it stay active.
13032 // Otherwise, blur the active item since it is no longer visible.
13033 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
13034 clearTimeout( this.timer );
13035 }
13036 }
13037 }
13038 },
13039 "mouseenter .ui-menu-item": function( event ) {
13040 var target = $( event.currentTarget );
13041 // Remove ui-state-active class from siblings of the newly focused menu item
13042 // to avoid a jump caused by adjacent elements both having a class with a border
13043 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
13044 this.focus( event, target );
13045 },
13046 mouseleave: "collapseAll",
13047 "mouseleave .ui-menu": "collapseAll",
13048 focus: function( event, keepActiveItem ) {
13049 // If there's already an active item, keep it active
13050 // If not, activate the first item
13051 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
13052
13053 if ( !keepActiveItem ) {
13054 this.focus( event, item );
13055 }
13056 },
13057 blur: function( event ) {
13058 this._delay(function() {
13059 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
13060 this.collapseAll( event );
13061 }
13062 });
13063 },
13064 keydown: "_keydown"
13065 });
13066
13067 this.refresh();
13068
13069 // Clicks outside of a menu collapse any open menus
13070 this._on( this.document, {
13071 click: function( event ) {
13072 if ( !$( event.target ).closest( ".ui-menu" ).length ) {
13073 this.collapseAll( event );
13074 }
13075
13076 // Reset the mouseHandled flag
13077 this.mouseHandled = false;
13078 }
13079 });
13080 },
13081
13082 _destroy: function() {
13083 // Destroy (sub)menus
13084 this.element
13085 .removeAttr( "aria-activedescendant" )
13086 .find( ".ui-menu" ).addBack()
13087 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
13088 .removeAttr( "role" )
13089 .removeAttr( "tabIndex" )
13090 .removeAttr( "aria-labelledby" )
13091 .removeAttr( "aria-expanded" )
13092 .removeAttr( "aria-hidden" )
13093 .removeAttr( "aria-disabled" )
13094 .removeUniqueId()
13095 .show();
13096
13097 // Destroy menu items
13098 this.element.find( ".ui-menu-item" )
13099 .removeClass( "ui-menu-item" )
13100 .removeAttr( "role" )
13101 .removeAttr( "aria-disabled" )
13102 .children( "a" )
13103 .removeUniqueId()
13104 .removeClass( "ui-corner-all ui-state-hover" )
13105 .removeAttr( "tabIndex" )
13106 .removeAttr( "role" )
13107 .removeAttr( "aria-haspopup" )
13108 .children().each( function() {
13109 var elem = $( this );
13110 if ( elem.data( "ui-menu-submenu-carat" ) ) {
13111 elem.remove();
13112 }
13113 });
13114
13115 // Destroy menu dividers
13116 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
13117 },
13118
13119 _keydown: function( event ) {
13120 /*jshint maxcomplexity:20*/
13121 var match, prev, character, skip, regex,
13122 preventDefault = true;
13123
13124 function escape( value ) {
13125 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
13126 }
13127
13128 switch ( event.keyCode ) {
13129 case $.ui.keyCode.PAGE_UP:
13130 this.previousPage( event );
13131 break;
13132 case $.ui.keyCode.PAGE_DOWN:
13133 this.nextPage( event );
13134 break;
13135 case $.ui.keyCode.HOME:
13136 this._move( "first", "first", event );
13137 break;
13138 case $.ui.keyCode.END:
13139 this._move( "last", "last", event );
13140 break;
13141 case $.ui.keyCode.UP:
13142 this.previous( event );
13143 break;
13144 case $.ui.keyCode.DOWN:
13145 this.next( event );
13146 break;
13147 case $.ui.keyCode.LEFT:
13148 this.collapse( event );
13149 break;
13150 case $.ui.keyCode.RIGHT:
13151 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
13152 this.expand( event );
13153 }
13154 break;
13155 case $.ui.keyCode.ENTER:
13156 case $.ui.keyCode.SPACE:
13157 this._activate( event );
13158 break;
13159 case $.ui.keyCode.ESCAPE:
13160 this.collapse( event );
13161 break;
13162 default:
13163 preventDefault = false;
13164 prev = this.previousFilter || "";
13165 character = String.fromCharCode( event.keyCode );
13166 skip = false;
13167
13168 clearTimeout( this.filterTimer );
13169
13170 if ( character === prev ) {
13171 skip = true;
13172 } else {
13173 character = prev + character;
13174 }
13175
13176 regex = new RegExp( "^" + escape( character ), "i" );
13177 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
13178 return regex.test( $( this ).children( "a" ).text() );
13179 });
13180 match = skip && match.index( this.active.next() ) !== -1 ?
13181 this.active.nextAll( ".ui-menu-item" ) :
13182 match;
13183
13184 // If no matches on the current filter, reset to the last character pressed
13185 // to move down the menu to the first item that starts with that character
13186 if ( !match.length ) {
13187 character = String.fromCharCode( event.keyCode );
13188 regex = new RegExp( "^" + escape( character ), "i" );
13189 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
13190 return regex.test( $( this ).children( "a" ).text() );
13191 });
13192 }
13193
13194 if ( match.length ) {
13195 this.focus( event, match );
13196 if ( match.length > 1 ) {
13197 this.previousFilter = character;
13198 this.filterTimer = this._delay(function() {
13199 delete this.previousFilter;
13200 }, 1000 );
13201 } else {
13202 delete this.previousFilter;
13203 }
13204 } else {
13205 delete this.previousFilter;
13206 }
13207 }
13208
13209 if ( preventDefault ) {
13210 event.preventDefault();
13211 }
13212 },
13213
13214 _activate: function( event ) {
13215 if ( !this.active.is( ".ui-state-disabled" ) ) {
13216 if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
13217 this.expand( event );
13218 } else {
13219 this.select( event );
13220 }
13221 }
13222 },
13223
13224 refresh: function() {
13225 var menus,
13226 icon = this.options.icons.submenu,
13227 submenus = this.element.find( this.options.menus );
13228
13229 // Initialize nested menus
13230 submenus.filter( ":not(.ui-menu)" )
13231 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
13232 .hide()
13233 .attr({
13234 role: this.options.role,
13235 "aria-hidden": "true",
13236 "aria-expanded": "false"
13237 })
13238 .each(function() {
13239 var menu = $( this ),
13240 item = menu.prev( "a" ),
13241 submenuCarat = $( "<span>" )
13242 .addClass( "ui-menu-icon ui-icon " + icon )
13243 .data( "ui-menu-submenu-carat", true );
13244
13245 item
13246 .attr( "aria-haspopup", "true" )
13247 .prepend( submenuCarat );
13248 menu.attr( "aria-labelledby", item.attr( "id" ) );
13249 });
13250
13251 menus = submenus.add( this.element );
13252
13253 // Don't refresh list items that are already adapted
13254 menus.children( ":not(.ui-menu-item):has(a)" )
13255 .addClass( "ui-menu-item" )
13256 .attr( "role", "presentation" )
13257 .children( "a" )
13258 .uniqueId()
13259 .addClass( "ui-corner-all" )
13260 .attr({
13261 tabIndex: -1,
13262 role: this._itemRole()
13263 });
13264
13265 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
13266 menus.children( ":not(.ui-menu-item)" ).each(function() {
13267 var item = $( this );
13268 // hyphen, em dash, en dash
13269 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
13270 item.addClass( "ui-widget-content ui-menu-divider" );
13271 }
13272 });
13273
13274 // Add aria-disabled attribute to any disabled menu item
13275 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
13276
13277 // If the active item has been removed, blur the menu
13278 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
13279 this.blur();
13280 }
13281 },
13282
13283 _itemRole: function() {
13284 return {
13285 menu: "menuitem",
13286 listbox: "option"
13287 }[ this.options.role ];
13288 },
13289
13290 _setOption: function( key, value ) {
13291 if ( key === "icons" ) {
13292 this.element.find( ".ui-menu-icon" )
13293 .removeClass( this.options.icons.submenu )
13294 .addClass( value.submenu );
13295 }
13296 this._super( key, value );
13297 },
13298
13299 focus: function( event, item ) {
13300 var nested, focused;
13301 this.blur( event, event && event.type === "focus" );
13302
13303 this._scrollIntoView( item );
13304
13305 this.active = item.first();
13306 focused = this.active.children( "a" ).addClass( "ui-state-focus" );
13307 // Only update aria-activedescendant if there's a role
13308 // otherwise we assume focus is managed elsewhere
13309 if ( this.options.role ) {
13310 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
13311 }
13312
13313 // Highlight active parent menu item, if any
13314 this.active
13315 .parent()
13316 .closest( ".ui-menu-item" )
13317 .children( "a:first" )
13318 .addClass( "ui-state-active" );
13319
13320 if ( event && event.type === "keydown" ) {
13321 this._close();
13322 } else {
13323 this.timer = this._delay(function() {
13324 this._close();
13325 }, this.delay );
13326 }
13327
13328 nested = item.children( ".ui-menu" );
13329 if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
13330 this._startOpening(nested);
13331 }
13332 this.activeMenu = item.parent();
13333
13334 this._trigger( "focus", event, { item: item } );
13335 },
13336
13337 _scrollIntoView: function( item ) {
13338 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
13339 if ( this._hasScroll() ) {
13340 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
13341 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
13342 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
13343 scroll = this.activeMenu.scrollTop();
13344 elementHeight = this.activeMenu.height();
13345 itemHeight = item.height();
13346
13347 if ( offset < 0 ) {
13348 this.activeMenu.scrollTop( scroll + offset );
13349 } else if ( offset + itemHeight > elementHeight ) {
13350 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
13351 }
13352 }
13353 },
13354
13355 blur: function( event, fromFocus ) {
13356 if ( !fromFocus ) {
13357 clearTimeout( this.timer );
13358 }
13359
13360 if ( !this.active ) {
13361 return;
13362 }
13363
13364 this.active.children( "a" ).removeClass( "ui-state-focus" );
13365 this.active = null;
13366
13367 this._trigger( "blur", event, { item: this.active } );
13368 },
13369
13370 _startOpening: function( submenu ) {
13371 clearTimeout( this.timer );
13372
13373 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
13374 // shift in the submenu position when mousing over the carat icon
13375 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
13376 return;
13377 }
13378
13379 this.timer = this._delay(function() {
13380 this._close();
13381 this._open( submenu );
13382 }, this.delay );
13383 },
13384
13385 _open: function( submenu ) {
13386 var position = $.extend({
13387 of: this.active
13388 }, this.options.position );
13389
13390 clearTimeout( this.timer );
13391 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
13392 .hide()
13393 .attr( "aria-hidden", "true" );
13394
13395 submenu
13396 .show()
13397 .removeAttr( "aria-hidden" )
13398 .attr( "aria-expanded", "true" )
13399 .position( position );
13400 },
13401
13402 collapseAll: function( event, all ) {
13403 clearTimeout( this.timer );
13404 this.timer = this._delay(function() {
13405 // If we were passed an event, look for the submenu that contains the event
13406 var currentMenu = all ? this.element :
13407 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
13408
13409 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
13410 if ( !currentMenu.length ) {
13411 currentMenu = this.element;
13412 }
13413
13414 this._close( currentMenu );
13415
13416 this.blur( event );
13417 this.activeMenu = currentMenu;
13418 }, this.delay );
13419 },
13420
13421 // With no arguments, closes the currently active menu - if nothing is active
13422 // it closes all menus. If passed an argument, it will search for menus BELOW
13423 _close: function( startMenu ) {
13424 if ( !startMenu ) {
13425 startMenu = this.active ? this.active.parent() : this.element;
13426 }
13427
13428 startMenu
13429 .find( ".ui-menu" )
13430 .hide()
13431 .attr( "aria-hidden", "true" )
13432 .attr( "aria-expanded", "false" )
13433 .end()
13434 .find( "a.ui-state-active" )
13435 .removeClass( "ui-state-active" );
13436 },
13437
13438 collapse: function( event ) {
13439 var newItem = this.active &&
13440 this.active.parent().closest( ".ui-menu-item", this.element );
13441 if ( newItem && newItem.length ) {
13442 this._close();
13443 this.focus( event, newItem );
13444 }
13445 },
13446
13447 expand: function( event ) {
13448 var newItem = this.active &&
13449 this.active
13450 .children( ".ui-menu " )
13451 .children( ".ui-menu-item" )
13452 .first();
13453
13454 if ( newItem && newItem.length ) {
13455 this._open( newItem.parent() );
13456
13457 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
13458 this._delay(function() {
13459 this.focus( event, newItem );
13460 });
13461 }
13462 },
13463
13464 next: function( event ) {
13465 this._move( "next", "first", event );
13466 },
13467
13468 previous: function( event ) {
13469 this._move( "prev", "last", event );
13470 },
13471
13472 isFirstItem: function() {
13473 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
13474 },
13475
13476 isLastItem: function() {
13477 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
13478 },
13479
13480 _move: function( direction, filter, event ) {
13481 var next;
13482 if ( this.active ) {
13483 if ( direction === "first" || direction === "last" ) {
13484 next = this.active
13485 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
13486 .eq( -1 );
13487 } else {
13488 next = this.active
13489 [ direction + "All" ]( ".ui-menu-item" )
13490 .eq( 0 );
13491 }
13492 }
13493 if ( !next || !next.length || !this.active ) {
13494 next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
13495 }
13496
13497 this.focus( event, next );
13498 },
13499
13500 nextPage: function( event ) {
13501 var item, base, height;
13502
13503 if ( !this.active ) {
13504 this.next( event );
13505 return;
13506 }
13507 if ( this.isLastItem() ) {
13508 return;
13509 }
13510 if ( this._hasScroll() ) {
13511 base = this.active.offset().top;
13512 height = this.element.height();
13513 this.active.nextAll( ".ui-menu-item" ).each(function() {
13514 item = $( this );
13515 return item.offset().top - base - height < 0;
13516 });
13517
13518 this.focus( event, item );
13519 } else {
13520 this.focus( event, this.activeMenu.children( ".ui-menu-item" )
13521 [ !this.active ? "first" : "last" ]() );
13522 }
13523 },
13524
13525 previousPage: function( event ) {
13526 var item, base, height;
13527 if ( !this.active ) {
13528 this.next( event );
13529 return;
13530 }
13531 if ( this.isFirstItem() ) {
13532 return;
13533 }
13534 if ( this._hasScroll() ) {
13535 base = this.active.offset().top;
13536 height = this.element.height();
13537 this.active.prevAll( ".ui-menu-item" ).each(function() {
13538 item = $( this );
13539 return item.offset().top - base + height > 0;
13540 });
13541
13542 this.focus( event, item );
13543 } else {
13544 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
13545 }
13546 },
13547
13548 _hasScroll: function() {
13549 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
13550 },
13551
13552 select: function( event ) {
13553 // TODO: It should never be possible to not have an active item at this
13554 // point, but the tests don't trigger mouseenter before click.
13555 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
13556 var ui = { item: this.active };
13557 if ( !this.active.has( ".ui-menu" ).length ) {
13558 this.collapseAll( event, true );
13559 }
13560 this._trigger( "select", event, ui );
13561 }
13562 });
13563
13564 }( jQuery ));
13565 (function( $, undefined ) {
13566
13567 $.widget( "ui.progressbar", {
13568 version: "1.10.3",
13569 options: {
13570 max: 100,
13571 value: 0,
13572
13573 change: null,
13574 complete: null
13575 },
13576
13577 min: 0,
13578
13579 _create: function() {
13580 // Constrain initial value
13581 this.oldValue = this.options.value = this._constrainedValue();
13582
13583 this.element
13584 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
13585 .attr({
13586 // Only set static values, aria-valuenow and aria-valuemax are
13587 // set inside _refreshValue()
13588 role: "progressbar",
13589 "aria-valuemin": this.min
13590 });
13591
13592 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
13593 .appendTo( this.element );
13594
13595 this._refreshValue();
13596 },
13597
13598 _destroy: function() {
13599 this.element
13600 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
13601 .removeAttr( "role" )
13602 .removeAttr( "aria-valuemin" )
13603 .removeAttr( "aria-valuemax" )
13604 .removeAttr( "aria-valuenow" );
13605
13606 this.valueDiv.remove();
13607 },
13608
13609 value: function( newValue ) {
13610 if ( newValue === undefined ) {
13611 return this.options.value;
13612 }
13613
13614 this.options.value = this._constrainedValue( newValue );
13615 this._refreshValue();
13616 },
13617
13618 _constrainedValue: function( newValue ) {
13619 if ( newValue === undefined ) {
13620 newValue = this.options.value;
13621 }
13622
13623 this.indeterminate = newValue === false;
13624
13625 // sanitize value
13626 if ( typeof newValue !== "number" ) {
13627 newValue = 0;
13628 }
13629
13630 return this.indeterminate ? false :
13631 Math.min( this.options.max, Math.max( this.min, newValue ) );
13632 },
13633
13634 _setOptions: function( options ) {
13635 // Ensure "value" option is set after other values (like max)
13636 var value = options.value;
13637 delete options.value;
13638
13639 this._super( options );
13640
13641 this.options.value = this._constrainedValue( value );
13642 this._refreshValue();
13643 },
13644
13645 _setOption: function( key, value ) {
13646 if ( key === "max" ) {
13647 // Don't allow a max less than min
13648 value = Math.max( this.min, value );
13649 }
13650
13651 this._super( key, value );
13652 },
13653
13654 _percentage: function() {
13655 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13656 },
13657
13658 _refreshValue: function() {
13659 var value = this.options.value,
13660 percentage = this._percentage();
13661
13662 this.valueDiv
13663 .toggle( this.indeterminate || value > this.min )
13664 .toggleClass( "ui-corner-right", value === this.options.max )
13665 .width( percentage.toFixed(0) + "%" );
13666
13667 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
13668
13669 if ( this.indeterminate ) {
13670 this.element.removeAttr( "aria-valuenow" );
13671 if ( !this.overlayDiv ) {
13672 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
13673 }
13674 } else {
13675 this.element.attr({
13676 "aria-valuemax": this.options.max,
13677 "aria-valuenow": value
13678 });
13679 if ( this.overlayDiv ) {
13680 this.overlayDiv.remove();
13681 this.overlayDiv = null;
13682 }
13683 }
13684
13685 if ( this.oldValue !== value ) {
13686 this.oldValue = value;
13687 this._trigger( "change" );
13688 }
13689 if ( value === this.options.max ) {
13690 this._trigger( "complete" );
13691 }
13692 }
13693 });
13694
13695 })( jQuery );
13696 (function( $, undefined ) {
13697
13698 // number of pages in a slider
13699 // (how many times can you page up/down to go through the whole range)
13700 var numPages = 5;
13701
13702 $.widget( "ui.slider", $.ui.mouse, {
13703 version: "1.10.3",
13704 widgetEventPrefix: "slide",
13705
13706 options: {
13707 animate: false,
13708 distance: 0,
13709 max: 100,
13710 min: 0,
13711 orientation: "horizontal",
13712 range: false,
13713 step: 1,
13714 value: 0,
13715 values: null,
13716
13717 // callbacks
13718 change: null,
13719 slide: null,
13720 start: null,
13721 stop: null
13722 },
13723
13724 _create: function() {
13725 this._keySliding = false;
13726 this._mouseSliding = false;
13727 this._animateOff = true;
13728 this._handleIndex = null;
13729 this._detectOrientation();
13730 this._mouseInit();
13731
13732 this.element
13733 .addClass( "ui-slider" +
13734 " ui-slider-" + this.orientation +
13735 " ui-widget" +
13736 " ui-widget-content" +
13737 " ui-corner-all");
13738
13739 this._refresh();
13740 this._setOption( "disabled", this.options.disabled );
13741
13742 this._animateOff = false;
13743 },
13744
13745 _refresh: function() {
13746 this._createRange();
13747 this._createHandles();
13748 this._setupEvents();
13749 this._refreshValue();
13750 },
13751
13752 _createHandles: function() {
13753 var i, handleCount,
13754 options = this.options,
13755 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
13756 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
13757 handles = [];
13758
13759 handleCount = ( options.values && options.values.length ) || 1;
13760
13761 if ( existingHandles.length > handleCount ) {
13762 existingHandles.slice( handleCount ).remove();
13763 existingHandles = existingHandles.slice( 0, handleCount );
13764 }
13765
13766 for ( i = existingHandles.length; i < handleCount; i++ ) {
13767 handles.push( handle );
13768 }
13769
13770 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
13771
13772 this.handle = this.handles.eq( 0 );
13773
13774 this.handles.each(function( i ) {
13775 $( this ).data( "ui-slider-handle-index", i );
13776 });
13777 },
13778
13779 _createRange: function() {
13780 var options = this.options,
13781 classes = "";
13782
13783 if ( options.range ) {
13784 if ( options.range === true ) {
13785 if ( !options.values ) {
13786 options.values = [ this._valueMin(), this._valueMin() ];
13787 } else if ( options.values.length && options.values.length !== 2 ) {
13788 options.values = [ options.values[0], options.values[0] ];
13789 } else if ( $.isArray( options.values ) ) {
13790 options.values = options.values.slice(0);
13791 }
13792 }
13793
13794 if ( !this.range || !this.range.length ) {
13795 this.range = $( "<div></div>" )
13796 .appendTo( this.element );
13797
13798 classes = "ui-slider-range" +
13799 // note: this isn't the most fittingly semantic framework class for this element,
13800 // but worked best visually with a variety of themes
13801 " ui-widget-header ui-corner-all";
13802 } else {
13803 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
13804 // Handle range switching from true to min/max
13805 .css({
13806 "left": "",
13807 "bottom": ""
13808 });
13809 }
13810
13811 this.range.addClass( classes +
13812 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
13813 } else {
13814 this.range = $([]);
13815 }
13816 },
13817
13818 _setupEvents: function() {
13819 var elements = this.handles.add( this.range ).filter( "a" );
13820 this._off( elements );
13821 this._on( elements, this._handleEvents );
13822 this._hoverable( elements );
13823 this._focusable( elements );
13824 },
13825
13826 _destroy: function() {
13827 this.handles.remove();
13828 this.range.remove();
13829
13830 this.element
13831 .removeClass( "ui-slider" +
13832 " ui-slider-horizontal" +
13833 " ui-slider-vertical" +
13834 " ui-widget" +
13835 " ui-widget-content" +
13836 " ui-corner-all" );
13837
13838 this._mouseDestroy();
13839 },
13840
13841 _mouseCapture: function( event ) {
13842 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
13843 that = this,
13844 o = this.options;
13845
13846 if ( o.disabled ) {
13847 return false;
13848 }
13849
13850 this.elementSize = {
13851 width: this.element.outerWidth(),
13852 height: this.element.outerHeight()
13853 };
13854 this.elementOffset = this.element.offset();
13855
13856 position = { x: event.pageX, y: event.pageY };
13857 normValue = this._normValueFromMouse( position );
13858 distance = this._valueMax() - this._valueMin() + 1;
13859 this.handles.each(function( i ) {
13860 var thisDistance = Math.abs( normValue - that.values(i) );
13861 if (( distance > thisDistance ) ||
13862 ( distance === thisDistance &&
13863 (i === that._lastChangedValue || that.values(i) === o.min ))) {
13864 distance = thisDistance;
13865 closestHandle = $( this );
13866 index = i;
13867 }
13868 });
13869
13870 allowed = this._start( event, index );
13871 if ( allowed === false ) {
13872 return false;
13873 }
13874 this._mouseSliding = true;
13875
13876 this._handleIndex = index;
13877
13878 closestHandle
13879 .addClass( "ui-state-active" )
13880 .focus();
13881
13882 offset = closestHandle.offset();
13883 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
13884 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
13885 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
13886 top: event.pageY - offset.top -
13887 ( closestHandle.height() / 2 ) -
13888 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
13889 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
13890 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
13891 };
13892
13893 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
13894 this._slide( event, index, normValue );
13895 }
13896 this._animateOff = true;
13897 return true;
13898 },
13899
13900 _mouseStart: function() {
13901 return true;
13902 },
13903
13904 _mouseDrag: function( event ) {
13905 var position = { x: event.pageX, y: event.pageY },
13906 normValue = this._normValueFromMouse( position );
13907
13908 this._slide( event, this._handleIndex, normValue );
13909
13910 return false;
13911 },
13912
13913 _mouseStop: function( event ) {
13914 this.handles.removeClass( "ui-state-active" );
13915 this._mouseSliding = false;
13916
13917 this._stop( event, this._handleIndex );
13918 this._change( event, this._handleIndex );
13919
13920 this._handleIndex = null;
13921 this._clickOffset = null;
13922 this._animateOff = false;
13923
13924 return false;
13925 },
13926
13927 _detectOrientation: function() {
13928 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13929 },
13930
13931 _normValueFromMouse: function( position ) {
13932 var pixelTotal,
13933 pixelMouse,
13934 percentMouse,
13935 valueTotal,
13936 valueMouse;
13937
13938 if ( this.orientation === "horizontal" ) {
13939 pixelTotal = this.elementSize.width;
13940 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13941 } else {
13942 pixelTotal = this.elementSize.height;
13943 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13944 }
13945
13946 percentMouse = ( pixelMouse / pixelTotal );
13947 if ( percentMouse > 1 ) {
13948 percentMouse = 1;
13949 }
13950 if ( percentMouse < 0 ) {
13951 percentMouse = 0;
13952 }
13953 if ( this.orientation === "vertical" ) {
13954 percentMouse = 1 - percentMouse;
13955 }
13956
13957 valueTotal = this._valueMax() - this._valueMin();
13958 valueMouse = this._valueMin() + percentMouse * valueTotal;
13959
13960 return this._trimAlignValue( valueMouse );
13961 },
13962
13963 _start: function( event, index ) {
13964 var uiHash = {
13965 handle: this.handles[ index ],
13966 value: this.value()
13967 };
13968 if ( this.options.values && this.options.values.length ) {
13969 uiHash.value = this.values( index );
13970 uiHash.values = this.values();
13971 }
13972 return this._trigger( "start", event, uiHash );
13973 },
13974
13975 _slide: function( event, index, newVal ) {
13976 var otherVal,
13977 newValues,
13978 allowed;
13979
13980 if ( this.options.values && this.options.values.length ) {
13981 otherVal = this.values( index ? 0 : 1 );
13982
13983 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13984 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13985 ) {
13986 newVal = otherVal;
13987 }
13988
13989 if ( newVal !== this.values( index ) ) {
13990 newValues = this.values();
13991 newValues[ index ] = newVal;
13992 // A slide can be canceled by returning false from the slide callback
13993 allowed = this._trigger( "slide", event, {
13994 handle: this.handles[ index ],
13995 value: newVal,
13996 values: newValues
13997 } );
13998 otherVal = this.values( index ? 0 : 1 );
13999 if ( allowed !== false ) {
14000 this.values( index, newVal, true );
14001 }
14002 }
14003 } else {
14004 if ( newVal !== this.value() ) {
14005 // A slide can be canceled by returning false from the slide callback
14006 allowed = this._trigger( "slide", event, {
14007 handle: this.handles[ index ],
14008 value: newVal
14009 } );
14010 if ( allowed !== false ) {
14011 this.value( newVal );
14012 }
14013 }
14014 }
14015 },
14016
14017 _stop: function( event, index ) {
14018 var uiHash = {
14019 handle: this.handles[ index ],
14020 value: this.value()
14021 };
14022 if ( this.options.values && this.options.values.length ) {
14023 uiHash.value = this.values( index );
14024 uiHash.values = this.values();
14025 }
14026
14027 this._trigger( "stop", event, uiHash );
14028 },
14029
14030 _change: function( event, index ) {
14031 if ( !this._keySliding && !this._mouseSliding ) {
14032 var uiHash = {
14033 handle: this.handles[ index ],
14034 value: this.value()
14035 };
14036 if ( this.options.values && this.options.values.length ) {
14037 uiHash.value = this.values( index );
14038 uiHash.values = this.values();
14039 }
14040
14041 //store the last changed value index for reference when handles overlap
14042 this._lastChangedValue = index;
14043
14044 this._trigger( "change", event, uiHash );
14045 }
14046 },
14047
14048 value: function( newValue ) {
14049 if ( arguments.length ) {
14050 this.options.value = this._trimAlignValue( newValue );
14051 this._refreshValue();
14052 this._change( null, 0 );
14053 return;
14054 }
14055
14056 return this._value();
14057 },
14058
14059 values: function( index, newValue ) {
14060 var vals,
14061 newValues,
14062 i;
14063
14064 if ( arguments.length > 1 ) {
14065 this.options.values[ index ] = this._trimAlignValue( newValue );
14066 this._refreshValue();
14067 this._change( null, index );
14068 return;
14069 }
14070
14071 if ( arguments.length ) {
14072 if ( $.isArray( arguments[ 0 ] ) ) {
14073 vals = this.options.values;
14074 newValues = arguments[ 0 ];
14075 for ( i = 0; i < vals.length; i += 1 ) {
14076 vals[ i ] = this._trimAlignValue( newValues[ i ] );
14077 this._change( null, i );
14078 }
14079 this._refreshValue();
14080 } else {
14081 if ( this.options.values && this.options.values.length ) {
14082 return this._values( index );
14083 } else {
14084 return this.value();
14085 }
14086 }
14087 } else {
14088 return this._values();
14089 }
14090 },
14091
14092 _setOption: function( key, value ) {
14093 var i,
14094 valsLength = 0;
14095
14096 if ( key === "range" && this.options.range === true ) {
14097 if ( value === "min" ) {
14098 this.options.value = this._values( 0 );
14099 this.options.values = null;
14100 } else if ( value === "max" ) {
14101 this.options.value = this._values( this.options.values.length-1 );
14102 this.options.values = null;
14103 }
14104 }
14105
14106 if ( $.isArray( this.options.values ) ) {
14107 valsLength = this.options.values.length;
14108 }
14109
14110 $.Widget.prototype._setOption.apply( this, arguments );
14111
14112 switch ( key ) {
14113 case "orientation":
14114 this._detectOrientation();
14115 this.element
14116 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
14117 .addClass( "ui-slider-" + this.orientation );
14118 this._refreshValue();
14119 break;
14120 case "value":
14121 this._animateOff = true;
14122 this._refreshValue();
14123 this._change( null, 0 );
14124 this._animateOff = false;
14125 break;
14126 case "values":
14127 this._animateOff = true;
14128 this._refreshValue();
14129 for ( i = 0; i < valsLength; i += 1 ) {
14130 this._change( null, i );
14131 }
14132 this._animateOff = false;
14133 break;
14134 case "min":
14135 case "max":
14136 this._animateOff = true;
14137 this._refreshValue();
14138 this._animateOff = false;
14139 break;
14140 case "range":
14141 this._animateOff = true;
14142 this._refresh();
14143 this._animateOff = false;
14144 break;
14145 }
14146 },
14147
14148 //internal value getter
14149 // _value() returns value trimmed by min and max, aligned by step
14150 _value: function() {
14151 var val = this.options.value;
14152 val = this._trimAlignValue( val );
14153
14154 return val;
14155 },
14156
14157 //internal values getter
14158 // _values() returns array of values trimmed by min and max, aligned by step
14159 // _values( index ) returns single value trimmed by min and max, aligned by step
14160 _values: function( index ) {
14161 var val,
14162 vals,
14163 i;
14164
14165 if ( arguments.length ) {
14166 val = this.options.values[ index ];
14167 val = this._trimAlignValue( val );
14168
14169 return val;
14170 } else if ( this.options.values && this.options.values.length ) {
14171 // .slice() creates a copy of the array
14172 // this copy gets trimmed by min and max and then returned
14173 vals = this.options.values.slice();
14174 for ( i = 0; i < vals.length; i+= 1) {
14175 vals[ i ] = this._trimAlignValue( vals[ i ] );
14176 }
14177
14178 return vals;
14179 } else {
14180 return [];
14181 }
14182 },
14183
14184 // returns the step-aligned value that val is closest to, between (inclusive) min and max
14185 _trimAlignValue: function( val ) {
14186 if ( val <= this._valueMin() ) {
14187 return this._valueMin();
14188 }
14189 if ( val >= this._valueMax() ) {
14190 return this._valueMax();
14191 }
14192 var step = ( this.options.step > 0 ) ? this.options.step : 1,
14193 valModStep = (val - this._valueMin()) % step,
14194 alignValue = val - valModStep;
14195
14196 if ( Math.abs(valModStep) * 2 >= step ) {
14197 alignValue += ( valModStep > 0 ) ? step : ( -step );
14198 }
14199
14200 // Since JavaScript has problems with large floats, round
14201 // the final value to 5 digits after the decimal point (see #4124)
14202 return parseFloat( alignValue.toFixed(5) );
14203 },
14204
14205 _valueMin: function() {
14206 return this.options.min;
14207 },
14208
14209 _valueMax: function() {
14210 return this.options.max;
14211 },
14212
14213 _refreshValue: function() {
14214 var lastValPercent, valPercent, value, valueMin, valueMax,
14215 oRange = this.options.range,
14216 o = this.options,
14217 that = this,
14218 animate = ( !this._animateOff ) ? o.animate : false,
14219 _set = {};
14220
14221 if ( this.options.values && this.options.values.length ) {
14222 this.handles.each(function( i ) {
14223 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
14224 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
14225 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
14226 if ( that.options.range === true ) {
14227 if ( that.orientation === "horizontal" ) {
14228 if ( i === 0 ) {
14229 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
14230 }
14231 if ( i === 1 ) {
14232 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
14233 }
14234 } else {
14235 if ( i === 0 ) {
14236 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
14237 }
14238 if ( i === 1 ) {
14239 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
14240 }
14241 }
14242 }
14243 lastValPercent = valPercent;
14244 });
14245 } else {
14246 value = this.value();
14247 valueMin = this._valueMin();
14248 valueMax = this._valueMax();
14249 valPercent = ( valueMax !== valueMin ) ?
14250 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
14251 0;
14252 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
14253 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
14254
14255 if ( oRange === "min" && this.orientation === "horizontal" ) {
14256 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
14257 }
14258 if ( oRange === "max" && this.orientation === "horizontal" ) {
14259 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
14260 }
14261 if ( oRange === "min" && this.orientation === "vertical" ) {
14262 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
14263 }
14264 if ( oRange === "max" && this.orientation === "vertical" ) {
14265 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
14266 }
14267 }
14268 },
14269
14270 _handleEvents: {
14271 keydown: function( event ) {
14272 /*jshint maxcomplexity:25*/
14273 var allowed, curVal, newVal, step,
14274 index = $( event.target ).data( "ui-slider-handle-index" );
14275
14276 switch ( event.keyCode ) {
14277 case $.ui.keyCode.HOME:
14278 case $.ui.keyCode.END:
14279 case $.ui.keyCode.PAGE_UP:
14280 case $.ui.keyCode.PAGE_DOWN:
14281 case $.ui.keyCode.UP:
14282 case $.ui.keyCode.RIGHT:
14283 case $.ui.keyCode.DOWN:
14284 case $.ui.keyCode.LEFT:
14285 event.preventDefault();
14286 if ( !this._keySliding ) {
14287 this._keySliding = true;
14288 $( event.target ).addClass( "ui-state-active" );
14289 allowed = this._start( event, index );
14290 if ( allowed === false ) {
14291 return;
14292 }
14293 }
14294 break;
14295 }
14296
14297 step = this.options.step;
14298 if ( this.options.values && this.options.values.length ) {
14299 curVal = newVal = this.values( index );
14300 } else {
14301 curVal = newVal = this.value();
14302 }
14303
14304 switch ( event.keyCode ) {
14305 case $.ui.keyCode.HOME:
14306 newVal = this._valueMin();
14307 break;
14308 case $.ui.keyCode.END:
14309 newVal = this._valueMax();
14310 break;
14311 case $.ui.keyCode.PAGE_UP:
14312 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
14313 break;
14314 case $.ui.keyCode.PAGE_DOWN:
14315 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
14316 break;
14317 case $.ui.keyCode.UP:
14318 case $.ui.keyCode.RIGHT:
14319 if ( curVal === this._valueMax() ) {
14320 return;
14321 }
14322 newVal = this._trimAlignValue( curVal + step );
14323 break;
14324 case $.ui.keyCode.DOWN:
14325 case $.ui.keyCode.LEFT:
14326 if ( curVal === this._valueMin() ) {
14327 return;
14328 }
14329 newVal = this._trimAlignValue( curVal - step );
14330 break;
14331 }
14332
14333 this._slide( event, index, newVal );
14334 },
14335 click: function( event ) {
14336 event.preventDefault();
14337 },
14338 keyup: function( event ) {
14339 var index = $( event.target ).data( "ui-slider-handle-index" );
14340
14341 if ( this._keySliding ) {
14342 this._keySliding = false;
14343 this._stop( event, index );
14344 this._change( event, index );
14345 $( event.target ).removeClass( "ui-state-active" );
14346 }
14347 }
14348 }
14349
14350 });
14351
14352 }(jQuery));
14353 (function( $ ) {
14354
14355 function modifier( fn ) {
14356 return function() {
14357 var previous = this.element.val();
14358 fn.apply( this, arguments );
14359 this._refresh();
14360 if ( previous !== this.element.val() ) {
14361 this._trigger( "change" );
14362 }
14363 };
14364 }
14365
14366 $.widget( "ui.spinner", {
14367 version: "1.10.3",
14368 defaultElement: "<input>",
14369 widgetEventPrefix: "spin",
14370 options: {
14371 culture: null,
14372 icons: {
14373 down: "ui-icon-triangle-1-s",
14374 up: "ui-icon-triangle-1-n"
14375 },
14376 incremental: true,
14377 max: null,
14378 min: null,
14379 numberFormat: null,
14380 page: 10,
14381 step: 1,
14382
14383 change: null,
14384 spin: null,
14385 start: null,
14386 stop: null
14387 },
14388
14389 _create: function() {
14390 // handle string values that need to be parsed
14391 this._setOption( "max", this.options.max );
14392 this._setOption( "min", this.options.min );
14393 this._setOption( "step", this.options.step );
14394
14395 // format the value, but don't constrain
14396 this._value( this.element.val(), true );
14397
14398 this._draw();
14399 this._on( this._events );
14400 this._refresh();
14401
14402 // turning off autocomplete prevents the browser from remembering the
14403 // value when navigating through history, so we re-enable autocomplete
14404 // if the page is unloaded before the widget is destroyed. #7790
14405 this._on( this.window, {
14406 beforeunload: function() {
14407 this.element.removeAttr( "autocomplete" );
14408 }
14409 });
14410 },
14411
14412 _getCreateOptions: function() {
14413 var options = {},
14414 element = this.element;
14415
14416 $.each( [ "min", "max", "step" ], function( i, option ) {
14417 var value = element.attr( option );
14418 if ( value !== undefined && value.length ) {
14419 options[ option ] = value;
14420 }
14421 });
14422
14423 return options;
14424 },
14425
14426 _events: {
14427 keydown: function( event ) {
14428 if ( this._start( event ) && this._keydown( event ) ) {
14429 event.preventDefault();
14430 }
14431 },
14432 keyup: "_stop",
14433 focus: function() {
14434 this.previous = this.element.val();
14435 },
14436 blur: function( event ) {
14437 if ( this.cancelBlur ) {
14438 delete this.cancelBlur;
14439 return;
14440 }
14441
14442 this._stop();
14443 this._refresh();
14444 if ( this.previous !== this.element.val() ) {
14445 this._trigger( "change", event );
14446 }
14447 },
14448 mousewheel: function( event, delta ) {
14449 if ( !delta ) {
14450 return;
14451 }
14452 if ( !this.spinning && !this._start( event ) ) {
14453 return false;
14454 }
14455
14456 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14457 clearTimeout( this.mousewheelTimer );
14458 this.mousewheelTimer = this._delay(function() {
14459 if ( this.spinning ) {
14460 this._stop( event );
14461 }
14462 }, 100 );
14463 event.preventDefault();
14464 },
14465 "mousedown .ui-spinner-button": function( event ) {
14466 var previous;
14467
14468 // We never want the buttons to have focus; whenever the user is
14469 // interacting with the spinner, the focus should be on the input.
14470 // If the input is focused then this.previous is properly set from
14471 // when the input first received focus. If the input is not focused
14472 // then we need to set this.previous based on the value before spinning.
14473 previous = this.element[0] === this.document[0].activeElement ?
14474 this.previous : this.element.val();
14475 function checkFocus() {
14476 var isActive = this.element[0] === this.document[0].activeElement;
14477 if ( !isActive ) {
14478 this.element.focus();
14479 this.previous = previous;
14480 // support: IE
14481 // IE sets focus asynchronously, so we need to check if focus
14482 // moved off of the input because the user clicked on the button.
14483 this._delay(function() {
14484 this.previous = previous;
14485 });
14486 }
14487 }
14488
14489 // ensure focus is on (or stays on) the text field
14490 event.preventDefault();
14491 checkFocus.call( this );
14492
14493 // support: IE
14494 // IE doesn't prevent moving focus even with event.preventDefault()
14495 // so we set a flag to know when we should ignore the blur event
14496 // and check (again) if focus moved off of the input.
14497 this.cancelBlur = true;
14498 this._delay(function() {
14499 delete this.cancelBlur;
14500 checkFocus.call( this );
14501 });
14502
14503 if ( this._start( event ) === false ) {
14504 return;
14505 }
14506
14507 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14508 },
14509 "mouseup .ui-spinner-button": "_stop",
14510 "mouseenter .ui-spinner-button": function( event ) {
14511 // button will add ui-state-active if mouse was down while mouseleave and kept down
14512 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14513 return;
14514 }
14515
14516 if ( this._start( event ) === false ) {
14517 return false;
14518 }
14519 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14520 },
14521 // TODO: do we really want to consider this a stop?
14522 // shouldn't we just stop the repeater and wait until mouseup before
14523 // we trigger the stop event?
14524 "mouseleave .ui-spinner-button": "_stop"
14525 },
14526
14527 _draw: function() {
14528 var uiSpinner = this.uiSpinner = this.element
14529 .addClass( "ui-spinner-input" )
14530 .attr( "autocomplete", "off" )
14531 .wrap( this._uiSpinnerHtml() )
14532 .parent()
14533 // add buttons
14534 .append( this._buttonHtml() );
14535
14536 this.element.attr( "role", "spinbutton" );
14537
14538 // button bindings
14539 this.buttons = uiSpinner.find( ".ui-spinner-button" )
14540 .attr( "tabIndex", -1 )
14541 .button()
14542 .removeClass( "ui-corner-all" );
14543
14544 // IE 6 doesn't understand height: 50% for the buttons
14545 // unless the wrapper has an explicit height
14546 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14547 uiSpinner.height() > 0 ) {
14548 uiSpinner.height( uiSpinner.height() );
14549 }
14550
14551 // disable spinner if element was already disabled
14552 if ( this.options.disabled ) {
14553 this.disable();
14554 }
14555 },
14556
14557 _keydown: function( event ) {
14558 var options = this.options,
14559 keyCode = $.ui.keyCode;
14560
14561 switch ( event.keyCode ) {
14562 case keyCode.UP:
14563 this._repeat( null, 1, event );
14564 return true;
14565 case keyCode.DOWN:
14566 this._repeat( null, -1, event );
14567 return true;
14568 case keyCode.PAGE_UP:
14569 this._repeat( null, options.page, event );
14570 return true;
14571 case keyCode.PAGE_DOWN:
14572 this._repeat( null, -options.page, event );
14573 return true;
14574 }
14575
14576 return false;
14577 },
14578
14579 _uiSpinnerHtml: function() {
14580 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
14581 },
14582
14583 _buttonHtml: function() {
14584 return "" +
14585 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
14586 "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
14587 "</a>" +
14588 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
14589 "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
14590 "</a>";
14591 },
14592
14593 _start: function( event ) {
14594 if ( !this.spinning && this._trigger( "start", event ) === false ) {
14595 return false;
14596 }
14597
14598 if ( !this.counter ) {
14599 this.counter = 1;
14600 }
14601 this.spinning = true;
14602 return true;
14603 },
14604
14605 _repeat: function( i, steps, event ) {
14606 i = i || 500;
14607
14608 clearTimeout( this.timer );
14609 this.timer = this._delay(function() {
14610 this._repeat( 40, steps, event );
14611 }, i );
14612
14613 this._spin( steps * this.options.step, event );
14614 },
14615
14616 _spin: function( step, event ) {
14617 var value = this.value() || 0;
14618
14619 if ( !this.counter ) {
14620 this.counter = 1;
14621 }
14622
14623 value = this._adjustValue( value + step * this._increment( this.counter ) );
14624
14625 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
14626 this._value( value );
14627 this.counter++;
14628 }
14629 },
14630
14631 _increment: function( i ) {
14632 var incremental = this.options.incremental;
14633
14634 if ( incremental ) {
14635 return $.isFunction( incremental ) ?
14636 incremental( i ) :
14637 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
14638 }
14639
14640 return 1;
14641 },
14642
14643 _precision: function() {
14644 var precision = this._precisionOf( this.options.step );
14645 if ( this.options.min !== null ) {
14646 precision = Math.max( precision, this._precisionOf( this.options.min ) );
14647 }
14648 return precision;
14649 },
14650
14651 _precisionOf: function( num ) {
14652 var str = num.toString(),
14653 decimal = str.indexOf( "." );
14654 return decimal === -1 ? 0 : str.length - decimal - 1;
14655 },
14656
14657 _adjustValue: function( value ) {
14658 var base, aboveMin,
14659 options = this.options;
14660
14661 // make sure we're at a valid step
14662 // - find out where we are relative to the base (min or 0)
14663 base = options.min !== null ? options.min : 0;
14664 aboveMin = value - base;
14665 // - round to the nearest step
14666 aboveMin = Math.round(aboveMin / options.step) * options.step;
14667 // - rounding is based on 0, so adjust back to our base
14668 value = base + aboveMin;
14669
14670 // fix precision from bad JS floating point math
14671 value = parseFloat( value.toFixed( this._precision() ) );
14672
14673 // clamp the value
14674 if ( options.max !== null && value > options.max) {
14675 return options.max;
14676 }
14677 if ( options.min !== null && value < options.min ) {
14678 return options.min;
14679 }
14680
14681 return value;
14682 },
14683
14684 _stop: function( event ) {
14685 if ( !this.spinning ) {
14686 return;
14687 }
14688
14689 clearTimeout( this.timer );
14690 clearTimeout( this.mousewheelTimer );
14691 this.counter = 0;
14692 this.spinning = false;
14693 this._trigger( "stop", event );
14694 },
14695
14696 _setOption: function( key, value ) {
14697 if ( key === "culture" || key === "numberFormat" ) {
14698 var prevValue = this._parse( this.element.val() );
14699 this.options[ key ] = value;
14700 this.element.val( this._format( prevValue ) );
14701 return;
14702 }
14703
14704 if ( key === "max" || key === "min" || key === "step" ) {
14705 if ( typeof value === "string" ) {
14706 value = this._parse( value );
14707 }
14708 }
14709 if ( key === "icons" ) {
14710 this.buttons.first().find( ".ui-icon" )
14711 .removeClass( this.options.icons.up )
14712 .addClass( value.up );
14713 this.buttons.last().find( ".ui-icon" )
14714 .removeClass( this.options.icons.down )
14715 .addClass( value.down );
14716 }
14717
14718 this._super( key, value );
14719
14720 if ( key === "disabled" ) {
14721 if ( value ) {
14722 this.element.prop( "disabled", true );
14723 this.buttons.button( "disable" );
14724 } else {
14725 this.element.prop( "disabled", false );
14726 this.buttons.button( "enable" );
14727 }
14728 }
14729 },
14730
14731 _setOptions: modifier(function( options ) {
14732 this._super( options );
14733 this._value( this.element.val() );
14734 }),
14735
14736 _parse: function( val ) {
14737 if ( typeof val === "string" && val !== "" ) {
14738 val = window.Globalize && this.options.numberFormat ?
14739 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
14740 }
14741 return val === "" || isNaN( val ) ? null : val;
14742 },
14743
14744 _format: function( value ) {
14745 if ( value === "" ) {
14746 return "";
14747 }
14748 return window.Globalize && this.options.numberFormat ?
14749 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
14750 value;
14751 },
14752
14753 _refresh: function() {
14754 this.element.attr({
14755 "aria-valuemin": this.options.min,
14756 "aria-valuemax": this.options.max,
14757 // TODO: what should we do with values that can't be parsed?
14758 "aria-valuenow": this._parse( this.element.val() )
14759 });
14760 },
14761
14762 // update the value without triggering change
14763 _value: function( value, allowAny ) {
14764 var parsed;
14765 if ( value !== "" ) {
14766 parsed = this._parse( value );
14767 if ( parsed !== null ) {
14768 if ( !allowAny ) {
14769 parsed = this._adjustValue( parsed );
14770 }
14771 value = this._format( parsed );
14772 }
14773 }
14774 this.element.val( value );
14775 this._refresh();
14776 },
14777
14778 _destroy: function() {
14779 this.element
14780 .removeClass( "ui-spinner-input" )
14781 .prop( "disabled", false )
14782 .removeAttr( "autocomplete" )
14783 .removeAttr( "role" )
14784 .removeAttr( "aria-valuemin" )
14785 .removeAttr( "aria-valuemax" )
14786 .removeAttr( "aria-valuenow" );
14787 this.uiSpinner.replaceWith( this.element );
14788 },
14789
14790 stepUp: modifier(function( steps ) {
14791 this._stepUp( steps );
14792 }),
14793 _stepUp: function( steps ) {
14794 if ( this._start() ) {
14795 this._spin( (steps || 1) * this.options.step );
14796 this._stop();
14797 }
14798 },
14799
14800 stepDown: modifier(function( steps ) {
14801 this._stepDown( steps );
14802 }),
14803 _stepDown: function( steps ) {
14804 if ( this._start() ) {
14805 this._spin( (steps || 1) * -this.options.step );
14806 this._stop();
14807 }
14808 },
14809
14810 pageUp: modifier(function( pages ) {
14811 this._stepUp( (pages || 1) * this.options.page );
14812 }),
14813
14814 pageDown: modifier(function( pages ) {
14815 this._stepDown( (pages || 1) * this.options.page );
14816 }),
14817
14818 value: function( newVal ) {
14819 if ( !arguments.length ) {
14820 return this._parse( this.element.val() );
14821 }
14822 modifier( this._value ).call( this, newVal );
14823 },
14824
14825 widget: function() {
14826 return this.uiSpinner;
14827 }
14828 });
14829
14830 }( jQuery ) );
14831 (function( $, undefined ) {
14832
14833 var tabId = 0,
14834 rhash = /#.*$/;
14835
14836 function getNextTabId() {
14837 return ++tabId;
14838 }
14839
14840 function isLocal( anchor ) {
14841 return anchor.hash.length > 1 &&
14842 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
14843 decodeURIComponent( location.href.replace( rhash, "" ) );
14844 }
14845
14846 $.widget( "ui.tabs", {
14847 version: "1.10.3",
14848 delay: 300,
14849 options: {
14850 active: null,
14851 collapsible: false,
14852 event: "click",
14853 heightStyle: "content",
14854 hide: null,
14855 show: null,
14856
14857 // callbacks
14858 activate: null,
14859 beforeActivate: null,
14860 beforeLoad: null,
14861 load: null
14862 },
14863
14864 _create: function() {
14865 var that = this,
14866 options = this.options;
14867
14868 this.running = false;
14869
14870 this.element
14871 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
14872 .toggleClass( "ui-tabs-collapsible", options.collapsible )
14873 // Prevent users from focusing disabled tabs via click
14874 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
14875 if ( $( this ).is( ".ui-state-disabled" ) ) {
14876 event.preventDefault();
14877 }
14878 })
14879 // support: IE <9
14880 // Preventing the default action in mousedown doesn't prevent IE
14881 // from focusing the element, so if the anchor gets focused, blur.
14882 // We don't have to worry about focusing the previously focused
14883 // element since clicking on a non-focusable element should focus
14884 // the body anyway.
14885 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
14886 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
14887 this.blur();
14888 }
14889 });
14890
14891 this._processTabs();
14892 options.active = this._initialActive();
14893
14894 // Take disabling tabs via class attribute from HTML
14895 // into account and update option properly.
14896 if ( $.isArray( options.disabled ) ) {
14897 options.disabled = $.unique( options.disabled.concat(
14898 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
14899 return that.tabs.index( li );
14900 })
14901 ) ).sort();
14902 }
14903
14904 // check for length avoids error when initializing empty list
14905 if ( this.options.active !== false && this.anchors.length ) {
14906 this.active = this._findActive( options.active );
14907 } else {
14908 this.active = $();
14909 }
14910
14911 this._refresh();
14912
14913 if ( this.active.length ) {
14914 this.load( options.active );
14915 }
14916 },
14917
14918 _initialActive: function() {
14919 var active = this.options.active,
14920 collapsible = this.options.collapsible,
14921 locationHash = location.hash.substring( 1 );
14922
14923 if ( active === null ) {
14924 // check the fragment identifier in the URL
14925 if ( locationHash ) {
14926 this.tabs.each(function( i, tab ) {
14927 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
14928 active = i;
14929 return false;
14930 }
14931 });
14932 }
14933
14934 // check for a tab marked active via a class
14935 if ( active === null ) {
14936 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
14937 }
14938
14939 // no active tab, set to false
14940 if ( active === null || active === -1 ) {
14941 active = this.tabs.length ? 0 : false;
14942 }
14943 }
14944
14945 // handle numbers: negative, out of range
14946 if ( active !== false ) {
14947 active = this.tabs.index( this.tabs.eq( active ) );
14948 if ( active === -1 ) {
14949 active = collapsible ? false : 0;
14950 }
14951 }
14952
14953 // don't allow collapsible: false and active: false
14954 if ( !collapsible && active === false && this.anchors.length ) {
14955 active = 0;
14956 }
14957
14958 return active;
14959 },
14960
14961 _getCreateEventData: function() {
14962 return {
14963 tab: this.active,
14964 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
14965 };
14966 },
14967
14968 _tabKeydown: function( event ) {
14969 /*jshint maxcomplexity:15*/
14970 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
14971 selectedIndex = this.tabs.index( focusedTab ),
14972 goingForward = true;
14973
14974 if ( this._handlePageNav( event ) ) {
14975 return;
14976 }
14977
14978 switch ( event.keyCode ) {
14979 case $.ui.keyCode.RIGHT:
14980 case $.ui.keyCode.DOWN:
14981 selectedIndex++;
14982 break;
14983 case $.ui.keyCode.UP:
14984 case $.ui.keyCode.LEFT:
14985 goingForward = false;
14986 selectedIndex--;
14987 break;
14988 case $.ui.keyCode.END:
14989 selectedIndex = this.anchors.length - 1;
14990 break;
14991 case $.ui.keyCode.HOME:
14992 selectedIndex = 0;
14993 break;
14994 case $.ui.keyCode.SPACE:
14995 // Activate only, no collapsing
14996 event.preventDefault();
14997 clearTimeout( this.activating );
14998 this._activate( selectedIndex );
14999 return;
15000 case $.ui.keyCode.ENTER:
15001 // Toggle (cancel delayed activation, allow collapsing)
15002 event.preventDefault();
15003 clearTimeout( this.activating );
15004 // Determine if we should collapse or activate
15005 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15006 return;
15007 default:
15008 return;
15009 }
15010
15011 // Focus the appropriate tab, based on which key was pressed
15012 event.preventDefault();
15013 clearTimeout( this.activating );
15014 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15015
15016 // Navigating with control key will prevent automatic activation
15017 if ( !event.ctrlKey ) {
15018 // Update aria-selected immediately so that AT think the tab is already selected.
15019 // Otherwise AT may confuse the user by stating that they need to activate the tab,
15020 // but the tab will already be activated by the time the announcement finishes.
15021 focusedTab.attr( "aria-selected", "false" );
15022 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15023
15024 this.activating = this._delay(function() {
15025 this.option( "active", selectedIndex );
15026 }, this.delay );
15027 }
15028 },
15029
15030 _panelKeydown: function( event ) {
15031 if ( this._handlePageNav( event ) ) {
15032 return;
15033 }
15034
15035 // Ctrl+up moves focus to the current tab
15036 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15037 event.preventDefault();
15038 this.active.focus();
15039 }
15040 },
15041
15042 // Alt+page up/down moves focus to the previous/next tab (and activates)
15043 _handlePageNav: function( event ) {
15044 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15045 this._activate( this._focusNextTab( this.options.active - 1, false ) );
15046 return true;
15047 }
15048 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15049 this._activate( this._focusNextTab( this.options.active + 1, true ) );
15050 return true;
15051 }
15052 },
15053
15054 _findNextTab: function( index, goingForward ) {
15055 var lastTabIndex = this.tabs.length - 1;
15056
15057 function constrain() {
15058 if ( index > lastTabIndex ) {
15059 index = 0;
15060 }
15061 if ( index < 0 ) {
15062 index = lastTabIndex;
15063 }
15064 return index;
15065 }
15066
15067 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15068 index = goingForward ? index + 1 : index - 1;
15069 }
15070
15071 return index;
15072 },
15073
15074 _focusNextTab: function( index, goingForward ) {
15075 index = this._findNextTab( index, goingForward );
15076 this.tabs.eq( index ).focus();
15077 return index;
15078 },
15079
15080 _setOption: function( key, value ) {
15081 if ( key === "active" ) {
15082 // _activate() will handle invalid values and update this.options
15083 this._activate( value );
15084 return;
15085 }
15086
15087 if ( key === "disabled" ) {
15088 // don't use the widget factory's disabled handling
15089 this._setupDisabled( value );
15090 return;
15091 }
15092
15093 this._super( key, value);
15094
15095 if ( key === "collapsible" ) {
15096 this.element.toggleClass( "ui-tabs-collapsible", value );
15097 // Setting collapsible: false while collapsed; open first panel
15098 if ( !value && this.options.active === false ) {
15099 this._activate( 0 );
15100 }
15101 }
15102
15103 if ( key === "event" ) {
15104 this._setupEvents( value );
15105 }
15106
15107 if ( key === "heightStyle" ) {
15108 this._setupHeightStyle( value );
15109 }
15110 },
15111
15112 _tabId: function( tab ) {
15113 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
15114 },
15115
15116 _sanitizeSelector: function( hash ) {
15117 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15118 },
15119
15120 refresh: function() {
15121 var options = this.options,
15122 lis = this.tablist.children( ":has(a[href])" );
15123
15124 // get disabled tabs from class attribute from HTML
15125 // this will get converted to a boolean if needed in _refresh()
15126 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15127 return lis.index( tab );
15128 });
15129
15130 this._processTabs();
15131
15132 // was collapsed or no tabs
15133 if ( options.active === false || !this.anchors.length ) {
15134 options.active = false;
15135 this.active = $();
15136 // was active, but active tab is gone
15137 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15138 // all remaining tabs are disabled
15139 if ( this.tabs.length === options.disabled.length ) {
15140 options.active = false;
15141 this.active = $();
15142 // activate previous tab
15143 } else {
15144 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15145 }
15146 // was active, active tab still exists
15147 } else {
15148 // make sure active index is correct
15149 options.active = this.tabs.index( this.active );
15150 }
15151
15152 this._refresh();
15153 },
15154
15155 _refresh: function() {
15156 this._setupDisabled( this.options.disabled );
15157 this._setupEvents( this.options.event );
15158 this._setupHeightStyle( this.options.heightStyle );
15159
15160 this.tabs.not( this.active ).attr({
15161 "aria-selected": "false",
15162 tabIndex: -1
15163 });
15164 this.panels.not( this._getPanelForTab( this.active ) )
15165 .hide()
15166 .attr({
15167 "aria-expanded": "false",
15168 "aria-hidden": "true"
15169 });
15170
15171 // Make sure one tab is in the tab order
15172 if ( !this.active.length ) {
15173 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15174 } else {
15175 this.active
15176 .addClass( "ui-tabs-active ui-state-active" )
15177 .attr({
15178 "aria-selected": "true",
15179 tabIndex: 0
15180 });
15181 this._getPanelForTab( this.active )
15182 .show()
15183 .attr({
15184 "aria-expanded": "true",
15185 "aria-hidden": "false"
15186 });
15187 }
15188 },
15189
15190 _processTabs: function() {
15191 var that = this;
15192
15193 this.tablist = this._getList()
15194 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15195 .attr( "role", "tablist" );
15196
15197 this.tabs = this.tablist.find( "> li:has(a[href])" )
15198 .addClass( "ui-state-default ui-corner-top" )
15199 .attr({
15200 role: "tab",
15201 tabIndex: -1
15202 });
15203
15204 this.anchors = this.tabs.map(function() {
15205 return $( "a", this )[ 0 ];
15206 })
15207 .addClass( "ui-tabs-anchor" )
15208 .attr({
15209 role: "presentation",
15210 tabIndex: -1
15211 });
15212
15213 this.panels = $();
15214
15215 this.anchors.each(function( i, anchor ) {
15216 var selector, panel, panelId,
15217 anchorId = $( anchor ).uniqueId().attr( "id" ),
15218 tab = $( anchor ).closest( "li" ),
15219 originalAriaControls = tab.attr( "aria-controls" );
15220
15221 // inline tab
15222 if ( isLocal( anchor ) ) {
15223 selector = anchor.hash;
15224 panel = that.element.find( that._sanitizeSelector( selector ) );
15225 // remote tab
15226 } else {
15227 panelId = that._tabId( tab );
15228 selector = "#" + panelId;
15229 panel = that.element.find( selector );
15230 if ( !panel.length ) {
15231 panel = that._createPanel( panelId );
15232 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15233 }
15234 panel.attr( "aria-live", "polite" );
15235 }
15236
15237 if ( panel.length) {
15238 that.panels = that.panels.add( panel );
15239 }
15240 if ( originalAriaControls ) {
15241 tab.data( "ui-tabs-aria-controls", originalAriaControls );
15242 }
15243 tab.attr({
15244 "aria-controls": selector.substring( 1 ),
15245 "aria-labelledby": anchorId
15246 });
15247 panel.attr( "aria-labelledby", anchorId );
15248 });
15249
15250 this.panels
15251 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15252 .attr( "role", "tabpanel" );
15253 },
15254
15255 // allow overriding how to find the list for rare usage scenarios (#7715)
15256 _getList: function() {
15257 return this.element.find( "ol,ul" ).eq( 0 );
15258 },
15259
15260 _createPanel: function( id ) {
15261 return $( "<div>" )
15262 .attr( "id", id )
15263 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15264 .data( "ui-tabs-destroy", true );
15265 },
15266
15267 _setupDisabled: function( disabled ) {
15268 if ( $.isArray( disabled ) ) {
15269 if ( !disabled.length ) {
15270 disabled = false;
15271 } else if ( disabled.length === this.anchors.length ) {
15272 disabled = true;
15273 }
15274 }
15275
15276 // disable tabs
15277 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15278 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15279 $( li )
15280 .addClass( "ui-state-disabled" )
15281 .attr( "aria-disabled", "true" );
15282 } else {
15283 $( li )
15284 .removeClass( "ui-state-disabled" )
15285 .removeAttr( "aria-disabled" );
15286 }
15287 }
15288
15289 this.options.disabled = disabled;
15290 },
15291
15292 _setupEvents: function( event ) {
15293 var events = {
15294 click: function( event ) {
15295 event.preventDefault();
15296 }
15297 };
15298 if ( event ) {
15299 $.each( event.split(" "), function( index, eventName ) {
15300 events[ eventName ] = "_eventHandler";
15301 });
15302 }
15303
15304 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15305 this._on( this.anchors, events );
15306 this._on( this.tabs, { keydown: "_tabKeydown" } );
15307 this._on( this.panels, { keydown: "_panelKeydown" } );
15308
15309 this._focusable( this.tabs );
15310 this._hoverable( this.tabs );
15311 },
15312
15313 _setupHeightStyle: function( heightStyle ) {
15314 var maxHeight,
15315 parent = this.element.parent();
15316
15317 if ( heightStyle === "fill" ) {
15318 maxHeight = parent.height();
15319 maxHeight -= this.element.outerHeight() - this.element.height();
15320
15321 this.element.siblings( ":visible" ).each(function() {
15322 var elem = $( this ),
15323 position = elem.css( "position" );
15324
15325 if ( position === "absolute" || position === "fixed" ) {
15326 return;
15327 }
15328 maxHeight -= elem.outerHeight( true );
15329 });
15330
15331 this.element.children().not( this.panels ).each(function() {
15332 maxHeight -= $( this ).outerHeight( true );
15333 });
15334
15335 this.panels.each(function() {
15336 $( this ).height( Math.max( 0, maxHeight -
15337 $( this ).innerHeight() + $( this ).height() ) );
15338 })
15339 .css( "overflow", "auto" );
15340 } else if ( heightStyle === "auto" ) {
15341 maxHeight = 0;
15342 this.panels.each(function() {
15343 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15344 }).height( maxHeight );
15345 }
15346 },
15347
15348 _eventHandler: function( event ) {
15349 var options = this.options,
15350 active = this.active,
15351 anchor = $( event.currentTarget ),
15352 tab = anchor.closest( "li" ),
15353 clickedIsActive = tab[ 0 ] === active[ 0 ],
15354 collapsing = clickedIsActive && options.collapsible,
15355 toShow = collapsing ? $() : this._getPanelForTab( tab ),
15356 toHide = !active.length ? $() : this._getPanelForTab( active ),
15357 eventData = {
15358 oldTab: active,
15359 oldPanel: toHide,
15360 newTab: collapsing ? $() : tab,
15361 newPanel: toShow
15362 };
15363
15364 event.preventDefault();
15365
15366 if ( tab.hasClass( "ui-state-disabled" ) ||
15367 // tab is already loading
15368 tab.hasClass( "ui-tabs-loading" ) ||
15369 // can't switch durning an animation
15370 this.running ||
15371 // click on active header, but not collapsible
15372 ( clickedIsActive && !options.collapsible ) ||
15373 // allow canceling activation
15374 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15375 return;
15376 }
15377
15378 options.active = collapsing ? false : this.tabs.index( tab );
15379
15380 this.active = clickedIsActive ? $() : tab;
15381 if ( this.xhr ) {
15382 this.xhr.abort();
15383 }
15384
15385 if ( !toHide.length && !toShow.length ) {
15386 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15387 }
15388
15389 if ( toShow.length ) {
15390 this.load( this.tabs.index( tab ), event );
15391 }
15392 this._toggle( event, eventData );
15393 },
15394
15395 // handles show/hide for selecting tabs
15396 _toggle: function( event, eventData ) {
15397 var that = this,
15398 toShow = eventData.newPanel,
15399 toHide = eventData.oldPanel;
15400
15401 this.running = true;
15402
15403 function complete() {
15404 that.running = false;
15405 that._trigger( "activate", event, eventData );
15406 }
15407
15408 function show() {
15409 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15410
15411 if ( toShow.length && that.options.show ) {
15412 that._show( toShow, that.options.show, complete );
15413 } else {
15414 toShow.show();
15415 complete();
15416 }
15417 }
15418
15419 // start out by hiding, then showing, then completing
15420 if ( toHide.length && this.options.hide ) {
15421 this._hide( toHide, this.options.hide, function() {
15422 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15423 show();
15424 });
15425 } else {
15426 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15427 toHide.hide();
15428 show();
15429 }
15430
15431 toHide.attr({
15432 "aria-expanded": "false",
15433 "aria-hidden": "true"
15434 });
15435 eventData.oldTab.attr( "aria-selected", "false" );
15436 // If we're switching tabs, remove the old tab from the tab order.
15437 // If we're opening from collapsed state, remove the previous tab from the tab order.
15438 // If we're collapsing, then keep the collapsing tab in the tab order.
15439 if ( toShow.length && toHide.length ) {
15440 eventData.oldTab.attr( "tabIndex", -1 );
15441 } else if ( toShow.length ) {
15442 this.tabs.filter(function() {
15443 return $( this ).attr( "tabIndex" ) === 0;
15444 })
15445 .attr( "tabIndex", -1 );
15446 }
15447
15448 toShow.attr({
15449 "aria-expanded": "true",
15450 "aria-hidden": "false"
15451 });
15452 eventData.newTab.attr({
15453 "aria-selected": "true",
15454 tabIndex: 0
15455 });
15456 },
15457
15458 _activate: function( index ) {
15459 var anchor,
15460 active = this._findActive( index );
15461
15462 // trying to activate the already active panel
15463 if ( active[ 0 ] === this.active[ 0 ] ) {
15464 return;
15465 }
15466
15467 // trying to collapse, simulate a click on the current active header
15468 if ( !active.length ) {
15469 active = this.active;
15470 }
15471
15472 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15473 this._eventHandler({
15474 target: anchor,
15475 currentTarget: anchor,
15476 preventDefault: $.noop
15477 });
15478 },
15479
15480 _findActive: function( index ) {
15481 return index === false ? $() : this.tabs.eq( index );
15482 },
15483
15484 _getIndex: function( index ) {
15485 // meta-function to give users option to provide a href string instead of a numerical index.
15486 if ( typeof index === "string" ) {
15487 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15488 }
15489
15490 return index;
15491 },
15492
15493 _destroy: function() {
15494 if ( this.xhr ) {
15495 this.xhr.abort();
15496 }
15497
15498 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
15499
15500 this.tablist
15501 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15502 .removeAttr( "role" );
15503
15504 this.anchors
15505 .removeClass( "ui-tabs-anchor" )
15506 .removeAttr( "role" )
15507 .removeAttr( "tabIndex" )
15508 .removeUniqueId();
15509
15510 this.tabs.add( this.panels ).each(function() {
15511 if ( $.data( this, "ui-tabs-destroy" ) ) {
15512 $( this ).remove();
15513 } else {
15514 $( this )
15515 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
15516 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
15517 .removeAttr( "tabIndex" )
15518 .removeAttr( "aria-live" )
15519 .removeAttr( "aria-busy" )
15520 .removeAttr( "aria-selected" )
15521 .removeAttr( "aria-labelledby" )
15522 .removeAttr( "aria-hidden" )
15523 .removeAttr( "aria-expanded" )
15524 .removeAttr( "role" );
15525 }
15526 });
15527
15528 this.tabs.each(function() {
15529 var li = $( this ),
15530 prev = li.data( "ui-tabs-aria-controls" );
15531 if ( prev ) {
15532 li
15533 .attr( "aria-controls", prev )
15534 .removeData( "ui-tabs-aria-controls" );
15535 } else {
15536 li.removeAttr( "aria-controls" );
15537 }
15538 });
15539
15540 this.panels.show();
15541
15542 if ( this.options.heightStyle !== "content" ) {
15543 this.panels.css( "height", "" );
15544 }
15545 },
15546
15547 enable: function( index ) {
15548 var disabled = this.options.disabled;
15549 if ( disabled === false ) {
15550 return;
15551 }
15552
15553 if ( index === undefined ) {
15554 disabled = false;
15555 } else {
15556 index = this._getIndex( index );
15557 if ( $.isArray( disabled ) ) {
15558 disabled = $.map( disabled, function( num ) {
15559 return num !== index ? num : null;
15560 });
15561 } else {
15562 disabled = $.map( this.tabs, function( li, num ) {
15563 return num !== index ? num : null;
15564 });
15565 }
15566 }
15567 this._setupDisabled( disabled );
15568 },
15569
15570 disable: function( index ) {
15571 var disabled = this.options.disabled;
15572 if ( disabled === true ) {
15573 return;
15574 }
15575
15576 if ( index === undefined ) {
15577 disabled = true;
15578 } else {
15579 index = this._getIndex( index );
15580 if ( $.inArray( index, disabled ) !== -1 ) {
15581 return;
15582 }
15583 if ( $.isArray( disabled ) ) {
15584 disabled = $.merge( [ index ], disabled ).sort();
15585 } else {
15586 disabled = [ index ];
15587 }
15588 }
15589 this._setupDisabled( disabled );
15590 },
15591
15592 load: function( index, event ) {
15593 index = this._getIndex( index );
15594 var that = this,
15595 tab = this.tabs.eq( index ),
15596 anchor = tab.find( ".ui-tabs-anchor" ),
15597 panel = this._getPanelForTab( tab ),
15598 eventData = {
15599 tab: tab,
15600 panel: panel
15601 };
15602
15603 // not remote
15604 if ( isLocal( anchor[ 0 ] ) ) {
15605 return;
15606 }
15607
15608 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
15609
15610 // support: jQuery <1.8
15611 // jQuery <1.8 returns false if the request is canceled in beforeSend,
15612 // but as of 1.8, $.ajax() always returns a jqXHR object.
15613 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
15614 tab.addClass( "ui-tabs-loading" );
15615 panel.attr( "aria-busy", "true" );
15616
15617 this.xhr
15618 .success(function( response ) {
15619 // support: jQuery <1.8
15620 // http://bugs.jquery.com/ticket/11778
15621 setTimeout(function() {
15622 panel.html( response );
15623 that._trigger( "load", event, eventData );
15624 }, 1 );
15625 })
15626 .complete(function( jqXHR, status ) {
15627 // support: jQuery <1.8
15628 // http://bugs.jquery.com/ticket/11778
15629 setTimeout(function() {
15630 if ( status === "abort" ) {
15631 that.panels.stop( false, true );
15632 }
15633
15634 tab.removeClass( "ui-tabs-loading" );
15635 panel.removeAttr( "aria-busy" );
15636
15637 if ( jqXHR === that.xhr ) {
15638 delete that.xhr;
15639 }
15640 }, 1 );
15641 });
15642 }
15643 },
15644
15645 _ajaxSettings: function( anchor, event, eventData ) {
15646 var that = this;
15647 return {
15648 url: anchor.attr( "href" ),
15649 beforeSend: function( jqXHR, settings ) {
15650 return that._trigger( "beforeLoad", event,
15651 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
15652 }
15653 };
15654 },
15655
15656 _getPanelForTab: function( tab ) {
15657 var id = $( tab ).attr( "aria-controls" );
15658 return this.element.find( this._sanitizeSelector( "#" + id ) );
15659 }
15660 });
15661
15662 })( jQuery );
15663 (function( $ ) {
15664
15665 var increments = 0;
15666
15667 function addDescribedBy( elem, id ) {
15668 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
15669 describedby.push( id );
15670 elem
15671 .data( "ui-tooltip-id", id )
15672 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
15673 }
15674
15675 function removeDescribedBy( elem ) {
15676 var id = elem.data( "ui-tooltip-id" ),
15677 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
15678 index = $.inArray( id, describedby );
15679 if ( index !== -1 ) {
15680 describedby.splice( index, 1 );
15681 }
15682
15683 elem.removeData( "ui-tooltip-id" );
15684 describedby = $.trim( describedby.join( " " ) );
15685 if ( describedby ) {
15686 elem.attr( "aria-describedby", describedby );
15687 } else {
15688 elem.removeAttr( "aria-describedby" );
15689 }
15690 }
15691
15692 $.widget( "ui.tooltip", {
15693 version: "1.10.3",
15694 options: {
15695 content: function() {
15696 // support: IE<9, Opera in jQuery <1.7
15697 // .text() can't accept undefined, so coerce to a string
15698 var title = $( this ).attr( "title" ) || "";
15699 // Escape title, since we're going from an attribute to raw HTML
15700 return $( "<a>" ).text( title ).html();
15701 },
15702 hide: true,
15703 // Disabled elements have inconsistent behavior across browsers (#8661)
15704 items: "[title]:not([disabled])",
15705 position: {
15706 my: "left top+15",
15707 at: "left bottom",
15708 collision: "flipfit flip"
15709 },
15710 show: true,
15711 tooltipClass: null,
15712 track: false,
15713
15714 // callbacks
15715 close: null,
15716 open: null
15717 },
15718
15719 _create: function() {
15720 this._on({
15721 mouseover: "open",
15722 focusin: "open"
15723 });
15724
15725 // IDs of generated tooltips, needed for destroy
15726 this.tooltips = {};
15727 // IDs of parent tooltips where we removed the title attribute
15728 this.parents = {};
15729
15730 if ( this.options.disabled ) {
15731 this._disable();
15732 }
15733 },
15734
15735 _setOption: function( key, value ) {
15736 var that = this;
15737
15738 if ( key === "disabled" ) {
15739 this[ value ? "_disable" : "_enable" ]();
15740 this.options[ key ] = value;
15741 // disable element style changes
15742 return;
15743 }
15744
15745 this._super( key, value );
15746
15747 if ( key === "content" ) {
15748 $.each( this.tooltips, function( id, element ) {
15749 that._updateContent( element );
15750 });
15751 }
15752 },
15753
15754 _disable: function() {
15755 var that = this;
15756
15757 // close open tooltips
15758 $.each( this.tooltips, function( id, element ) {
15759 var event = $.Event( "blur" );
15760 event.target = event.currentTarget = element[0];
15761 that.close( event, true );
15762 });
15763
15764 // remove title attributes to prevent native tooltips
15765 this.element.find( this.options.items ).addBack().each(function() {
15766 var element = $( this );
15767 if ( element.is( "[title]" ) ) {
15768 element
15769 .data( "ui-tooltip-title", element.attr( "title" ) )
15770 .attr( "title", "" );
15771 }
15772 });
15773 },
15774
15775 _enable: function() {
15776 // restore title attributes
15777 this.element.find( this.options.items ).addBack().each(function() {
15778 var element = $( this );
15779 if ( element.data( "ui-tooltip-title" ) ) {
15780 element.attr( "title", element.data( "ui-tooltip-title" ) );
15781 }
15782 });
15783 },
15784
15785 open: function( event ) {
15786 var that = this,
15787 target = $( event ? event.target : this.element )
15788 // we need closest here due to mouseover bubbling,
15789 // but always pointing at the same event target
15790 .closest( this.options.items );
15791
15792 // No element to show a tooltip for or the tooltip is already open
15793 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
15794 return;
15795 }
15796
15797 if ( target.attr( "title" ) ) {
15798 target.data( "ui-tooltip-title", target.attr( "title" ) );
15799 }
15800
15801 target.data( "ui-tooltip-open", true );
15802
15803 // kill parent tooltips, custom or native, for hover
15804 if ( event && event.type === "mouseover" ) {
15805 target.parents().each(function() {
15806 var parent = $( this ),
15807 blurEvent;
15808 if ( parent.data( "ui-tooltip-open" ) ) {
15809 blurEvent = $.Event( "blur" );
15810 blurEvent.target = blurEvent.currentTarget = this;
15811 that.close( blurEvent, true );
15812 }
15813 if ( parent.attr( "title" ) ) {
15814 parent.uniqueId();
15815 that.parents[ this.id ] = {
15816 element: this,
15817 title: parent.attr( "title" )
15818 };
15819 parent.attr( "title", "" );
15820 }
15821 });
15822 }
15823
15824 this._updateContent( target, event );
15825 },
15826
15827 _updateContent: function( target, event ) {
15828 var content,
15829 contentOption = this.options.content,
15830 that = this,
15831 eventType = event ? event.type : null;
15832
15833 if ( typeof contentOption === "string" ) {
15834 return this._open( event, target, contentOption );
15835 }
15836
15837 content = contentOption.call( target[0], function( response ) {
15838 // ignore async response if tooltip was closed already
15839 if ( !target.data( "ui-tooltip-open" ) ) {
15840 return;
15841 }
15842 // IE may instantly serve a cached response for ajax requests
15843 // delay this call to _open so the other call to _open runs first
15844 that._delay(function() {
15845 // jQuery creates a special event for focusin when it doesn't
15846 // exist natively. To improve performance, the native event
15847 // object is reused and the type is changed. Therefore, we can't
15848 // rely on the type being correct after the event finished
15849 // bubbling, so we set it back to the previous value. (#8740)
15850 if ( event ) {
15851 event.type = eventType;
15852 }
15853 this._open( event, target, response );
15854 });
15855 });
15856 if ( content ) {
15857 this._open( event, target, content );
15858 }
15859 },
15860
15861 _open: function( event, target, content ) {
15862 var tooltip, events, delayedShow,
15863 positionOption = $.extend( {}, this.options.position );
15864
15865 if ( !content ) {
15866 return;
15867 }
15868
15869 // Content can be updated multiple times. If the tooltip already
15870 // exists, then just update the content and bail.
15871 tooltip = this._find( target );
15872 if ( tooltip.length ) {
15873 tooltip.find( ".ui-tooltip-content" ).html( content );
15874 return;
15875 }
15876
15877 // if we have a title, clear it to prevent the native tooltip
15878 // we have to check first to avoid defining a title if none exists
15879 // (we don't want to cause an element to start matching [title])
15880 //
15881 // We use removeAttr only for key events, to allow IE to export the correct
15882 // accessible attributes. For mouse events, set to empty string to avoid
15883 // native tooltip showing up (happens only when removing inside mouseover).
15884 if ( target.is( "[title]" ) ) {
15885 if ( event && event.type === "mouseover" ) {
15886 target.attr( "title", "" );
15887 } else {
15888 target.removeAttr( "title" );
15889 }
15890 }
15891
15892 tooltip = this._tooltip( target );
15893 addDescribedBy( target, tooltip.attr( "id" ) );
15894 tooltip.find( ".ui-tooltip-content" ).html( content );
15895
15896 function position( event ) {
15897 positionOption.of = event;
15898 if ( tooltip.is( ":hidden" ) ) {
15899 return;
15900 }
15901 tooltip.position( positionOption );
15902 }
15903 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
15904 this._on( this.document, {
15905 mousemove: position
15906 });
15907 // trigger once to override element-relative positioning
15908 position( event );
15909 } else {
15910 tooltip.position( $.extend({
15911 of: target
15912 }, this.options.position ) );
15913 }
15914
15915 tooltip.hide();
15916
15917 this._show( tooltip, this.options.show );
15918 // Handle tracking tooltips that are shown with a delay (#8644). As soon
15919 // as the tooltip is visible, position the tooltip using the most recent
15920 // event.
15921 if ( this.options.show && this.options.show.delay ) {
15922 delayedShow = this.delayedShow = setInterval(function() {
15923 if ( tooltip.is( ":visible" ) ) {
15924 position( positionOption.of );
15925 clearInterval( delayedShow );
15926 }
15927 }, $.fx.interval );
15928 }
15929
15930 this._trigger( "open", event, { tooltip: tooltip } );
15931
15932 events = {
15933 keyup: function( event ) {
15934 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
15935 var fakeEvent = $.Event(event);
15936 fakeEvent.currentTarget = target[0];
15937 this.close( fakeEvent, true );
15938 }
15939 },
15940 remove: function() {
15941 this._removeTooltip( tooltip );
15942 }
15943 };
15944 if ( !event || event.type === "mouseover" ) {
15945 events.mouseleave = "close";
15946 }
15947 if ( !event || event.type === "focusin" ) {
15948 events.focusout = "close";
15949 }
15950 this._on( true, target, events );
15951 },
15952
15953 close: function( event ) {
15954 var that = this,
15955 target = $( event ? event.currentTarget : this.element ),
15956 tooltip = this._find( target );
15957
15958 // disabling closes the tooltip, so we need to track when we're closing
15959 // to avoid an infinite loop in case the tooltip becomes disabled on close
15960 if ( this.closing ) {
15961 return;
15962 }
15963
15964 // Clear the interval for delayed tracking tooltips
15965 clearInterval( this.delayedShow );
15966
15967 // only set title if we had one before (see comment in _open())
15968 if ( target.data( "ui-tooltip-title" ) ) {
15969 target.attr( "title", target.data( "ui-tooltip-title" ) );
15970 }
15971
15972 removeDescribedBy( target );
15973
15974 tooltip.stop( true );
15975 this._hide( tooltip, this.options.hide, function() {
15976 that._removeTooltip( $( this ) );
15977 });
15978
15979 target.removeData( "ui-tooltip-open" );
15980 this._off( target, "mouseleave focusout keyup" );
15981 // Remove 'remove' binding only on delegated targets
15982 if ( target[0] !== this.element[0] ) {
15983 this._off( target, "remove" );
15984 }
15985 this._off( this.document, "mousemove" );
15986
15987 if ( event && event.type === "mouseleave" ) {
15988 $.each( this.parents, function( id, parent ) {
15989 $( parent.element ).attr( "title", parent.title );
15990 delete that.parents[ id ];
15991 });
15992 }
15993
15994 this.closing = true;
15995 this._trigger( "close", event, { tooltip: tooltip } );
15996 this.closing = false;
15997 },
15998
15999 _tooltip: function( element ) {
16000 var id = "ui-tooltip-" + increments++,
16001 tooltip = $( "<div>" )
16002 .attr({
16003 id: id,
16004 role: "tooltip"
16005 })
16006 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16007 ( this.options.tooltipClass || "" ) );
16008 $( "<div>" )
16009 .addClass( "ui-tooltip-content" )
16010 .appendTo( tooltip );
16011 tooltip.appendTo( this.document[0].body );
16012 this.tooltips[ id ] = element;
16013 return tooltip;
16014 },
16015
16016 _find: function( target ) {
16017 var id = target.data( "ui-tooltip-id" );
16018 return id ? $( "#" + id ) : $();
16019 },
16020
16021 _removeTooltip: function( tooltip ) {
16022 tooltip.remove();
16023 delete this.tooltips[ tooltip.attr( "id" ) ];
16024 },
16025
16026 _destroy: function() {
16027 var that = this;
16028
16029 // close open tooltips
16030 $.each( this.tooltips, function( id, element ) {
16031 // Delegate to close method to handle common cleanup
16032 var event = $.Event( "blur" );
16033 event.target = event.currentTarget = element[0];
16034 that.close( event, true );
16035
16036 // Remove immediately; destroying an open tooltip doesn't use the
16037 // hide animation
16038 $( "#" + id ).remove();
16039
16040 // Restore the title
16041 if ( element.data( "ui-tooltip-title" ) ) {
16042 element.attr( "title", element.data( "ui-tooltip-title" ) );
16043 element.removeData( "ui-tooltip-title" );
16044 }
16045 });
16046 }
16047 });
16048
16049 }( jQuery ) );
16050 (function($, undefined) {
16051
16052 var dataSpace = "ui-effects-";
16053
16054 $.effects = {
16055 effect: {}
16056 };
16057
16058 /*!
16059 * jQuery Color Animations v2.1.2
16060 * https://github.com/jquery/jquery-color
16061 *
16062 * Copyright 2013 jQuery Foundation and other contributors
16063 * Released under the MIT license.
16064 * http://jquery.org/license
16065 *
16066 * Date: Wed Jan 16 08:47:09 2013 -0600
16067 */
16068 (function( jQuery, undefined ) {
16069
16070 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
16071
16072 // plusequals test for += 100 -= 100
16073 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
16074 // a set of RE's that can match strings and generate color tuples.
16075 stringParsers = [{
16076 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
16077 parse: function( execResult ) {
16078 return [
16079 execResult[ 1 ],
16080 execResult[ 2 ],
16081 execResult[ 3 ],
16082 execResult[ 4 ]
16083 ];
16084 }
16085 }, {
16086 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
16087 parse: function( execResult ) {
16088 return [
16089 execResult[ 1 ] * 2.55,
16090 execResult[ 2 ] * 2.55,
16091 execResult[ 3 ] * 2.55,
16092 execResult[ 4 ]
16093 ];
16094 }
16095 }, {
16096 // this regex ignores A-F because it's compared against an already lowercased string
16097 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
16098 parse: function( execResult ) {
16099 return [
16100 parseInt( execResult[ 1 ], 16 ),
16101 parseInt( execResult[ 2 ], 16 ),
16102 parseInt( execResult[ 3 ], 16 )
16103 ];
16104 }
16105 }, {
16106 // this regex ignores A-F because it's compared against an already lowercased string
16107 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
16108 parse: function( execResult ) {
16109 return [
16110 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
16111 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
16112 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
16113 ];
16114 }
16115 }, {
16116 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
16117 space: "hsla",
16118 parse: function( execResult ) {
16119 return [
16120 execResult[ 1 ],
16121 execResult[ 2 ] / 100,
16122 execResult[ 3 ] / 100,
16123 execResult[ 4 ]
16124 ];
16125 }
16126 }],
16127
16128 // jQuery.Color( )
16129 color = jQuery.Color = function( color, green, blue, alpha ) {
16130 return new jQuery.Color.fn.parse( color, green, blue, alpha );
16131 },
16132 spaces = {
16133 rgba: {
16134 props: {
16135 red: {
16136 idx: 0,
16137 type: "byte"
16138 },
16139 green: {
16140 idx: 1,
16141 type: "byte"
16142 },
16143 blue: {
16144 idx: 2,
16145 type: "byte"
16146 }
16147 }
16148 },
16149
16150 hsla: {
16151 props: {
16152 hue: {
16153 idx: 0,
16154 type: "degrees"
16155 },
16156 saturation: {
16157 idx: 1,
16158 type: "percent"
16159 },
16160 lightness: {
16161 idx: 2,
16162 type: "percent"
16163 }
16164 }
16165 }
16166 },
16167 propTypes = {
16168 "byte": {
16169 floor: true,
16170 max: 255
16171 },
16172 "percent": {
16173 max: 1
16174 },
16175 "degrees": {
16176 mod: 360,
16177 floor: true
16178 }
16179 },
16180 support = color.support = {},
16181
16182 // element for support tests
16183 supportElem = jQuery( "<p>" )[ 0 ],
16184
16185 // colors = jQuery.Color.names
16186 colors,
16187
16188 // local aliases of functions called often
16189 each = jQuery.each;
16190
16191 // determine rgba support immediately
16192 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
16193 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
16194
16195 // define cache name and alpha properties
16196 // for rgba and hsla spaces
16197 each( spaces, function( spaceName, space ) {
16198 space.cache = "_" + spaceName;
16199 space.props.alpha = {
16200 idx: 3,
16201 type: "percent",
16202 def: 1
16203 };
16204 });
16205
16206 function clamp( value, prop, allowEmpty ) {
16207 var type = propTypes[ prop.type ] || {};
16208
16209 if ( value == null ) {
16210 return (allowEmpty || !prop.def) ? null : prop.def;
16211 }
16212
16213 // ~~ is an short way of doing floor for positive numbers
16214 value = type.floor ? ~~value : parseFloat( value );
16215
16216 // IE will pass in empty strings as value for alpha,
16217 // which will hit this case
16218 if ( isNaN( value ) ) {
16219 return prop.def;
16220 }
16221
16222 if ( type.mod ) {
16223 // we add mod before modding to make sure that negatives values
16224 // get converted properly: -10 -> 350
16225 return (value + type.mod) % type.mod;
16226 }
16227
16228 // for now all property types without mod have min and max
16229 return 0 > value ? 0 : type.max < value ? type.max : value;
16230 }
16231
16232 function stringParse( string ) {
16233 var inst = color(),
16234 rgba = inst._rgba = [];
16235
16236 string = string.toLowerCase();
16237
16238 each( stringParsers, function( i, parser ) {
16239 var parsed,
16240 match = parser.re.exec( string ),
16241 values = match && parser.parse( match ),
16242 spaceName = parser.space || "rgba";
16243
16244 if ( values ) {
16245 parsed = inst[ spaceName ]( values );
16246
16247 // if this was an rgba parse the assignment might happen twice
16248 // oh well....
16249 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
16250 rgba = inst._rgba = parsed._rgba;
16251
16252 // exit each( stringParsers ) here because we matched
16253 return false;
16254 }
16255 });
16256
16257 // Found a stringParser that handled it
16258 if ( rgba.length ) {
16259
16260 // if this came from a parsed string, force "transparent" when alpha is 0
16261 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
16262 if ( rgba.join() === "0,0,0,0" ) {
16263 jQuery.extend( rgba, colors.transparent );
16264 }
16265 return inst;
16266 }
16267
16268 // named colors
16269 return colors[ string ];
16270 }
16271
16272 color.fn = jQuery.extend( color.prototype, {
16273 parse: function( red, green, blue, alpha ) {
16274 if ( red === undefined ) {
16275 this._rgba = [ null, null, null, null ];
16276 return this;
16277 }
16278 if ( red.jquery || red.nodeType ) {
16279 red = jQuery( red ).css( green );
16280 green = undefined;
16281 }
16282
16283 var inst = this,
16284 type = jQuery.type( red ),
16285 rgba = this._rgba = [];
16286
16287 // more than 1 argument specified - assume ( red, green, blue, alpha )
16288 if ( green !== undefined ) {
16289 red = [ red, green, blue, alpha ];
16290 type = "array";
16291 }
16292
16293 if ( type === "string" ) {
16294 return this.parse( stringParse( red ) || colors._default );
16295 }
16296
16297 if ( type === "array" ) {
16298 each( spaces.rgba.props, function( key, prop ) {
16299 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
16300 });
16301 return this;
16302 }
16303
16304 if ( type === "object" ) {
16305 if ( red instanceof color ) {
16306 each( spaces, function( spaceName, space ) {
16307 if ( red[ space.cache ] ) {
16308 inst[ space.cache ] = red[ space.cache ].slice();
16309 }
16310 });
16311 } else {
16312 each( spaces, function( spaceName, space ) {
16313 var cache = space.cache;
16314 each( space.props, function( key, prop ) {
16315
16316 // if the cache doesn't exist, and we know how to convert
16317 if ( !inst[ cache ] && space.to ) {
16318
16319 // if the value was null, we don't need to copy it
16320 // if the key was alpha, we don't need to copy it either
16321 if ( key === "alpha" || red[ key ] == null ) {
16322 return;
16323 }
16324 inst[ cache ] = space.to( inst._rgba );
16325 }
16326
16327 // this is the only case where we allow nulls for ALL properties.
16328 // call clamp with alwaysAllowEmpty
16329 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
16330 });
16331
16332 // everything defined but alpha?
16333 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
16334 // use the default of 1
16335 inst[ cache ][ 3 ] = 1;
16336 if ( space.from ) {
16337 inst._rgba = space.from( inst[ cache ] );
16338 }
16339 }
16340 });
16341 }
16342 return this;
16343 }
16344 },
16345 is: function( compare ) {
16346 var is = color( compare ),
16347 same = true,
16348 inst = this;
16349
16350 each( spaces, function( _, space ) {
16351 var localCache,
16352 isCache = is[ space.cache ];
16353 if (isCache) {
16354 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
16355 each( space.props, function( _, prop ) {
16356 if ( isCache[ prop.idx ] != null ) {
16357 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
16358 return same;
16359 }
16360 });
16361 }
16362 return same;
16363 });
16364 return same;
16365 },
16366 _space: function() {
16367 var used = [],
16368 inst = this;
16369 each( spaces, function( spaceName, space ) {
16370 if ( inst[ space.cache ] ) {
16371 used.push( spaceName );
16372 }
16373 });
16374 return used.pop();
16375 },
16376 transition: function( other, distance ) {
16377 var end = color( other ),
16378 spaceName = end._space(),
16379 space = spaces[ spaceName ],
16380 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
16381 start = startColor[ space.cache ] || space.to( startColor._rgba ),
16382 result = start.slice();
16383
16384 end = end[ space.cache ];
16385 each( space.props, function( key, prop ) {
16386 var index = prop.idx,
16387 startValue = start[ index ],
16388 endValue = end[ index ],
16389 type = propTypes[ prop.type ] || {};
16390
16391 // if null, don't override start value
16392 if ( endValue === null ) {
16393 return;
16394 }
16395 // if null - use end
16396 if ( startValue === null ) {
16397 result[ index ] = endValue;
16398 } else {
16399 if ( type.mod ) {
16400 if ( endValue - startValue > type.mod / 2 ) {
16401 startValue += type.mod;
16402 } else if ( startValue - endValue > type.mod / 2 ) {
16403 startValue -= type.mod;
16404 }
16405 }
16406 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
16407 }
16408 });
16409 return this[ spaceName ]( result );
16410 },
16411 blend: function( opaque ) {
16412 // if we are already opaque - return ourself
16413 if ( this._rgba[ 3 ] === 1 ) {
16414 return this;
16415 }
16416
16417 var rgb = this._rgba.slice(),
16418 a = rgb.pop(),
16419 blend = color( opaque )._rgba;
16420
16421 return color( jQuery.map( rgb, function( v, i ) {
16422 return ( 1 - a ) * blend[ i ] + a * v;
16423 }));
16424 },
16425 toRgbaString: function() {
16426 var prefix = "rgba(",
16427 rgba = jQuery.map( this._rgba, function( v, i ) {
16428 return v == null ? ( i > 2 ? 1 : 0 ) : v;
16429 });
16430
16431 if ( rgba[ 3 ] === 1 ) {
16432 rgba.pop();
16433 prefix = "rgb(";
16434 }
16435
16436 return prefix + rgba.join() + ")";
16437 },
16438 toHslaString: function() {
16439 var prefix = "hsla(",
16440 hsla = jQuery.map( this.hsla(), function( v, i ) {
16441 if ( v == null ) {
16442 v = i > 2 ? 1 : 0;
16443 }
16444
16445 // catch 1 and 2
16446 if ( i && i < 3 ) {
16447 v = Math.round( v * 100 ) + "%";
16448 }
16449 return v;
16450 });
16451
16452 if ( hsla[ 3 ] === 1 ) {
16453 hsla.pop();
16454 prefix = "hsl(";
16455 }
16456 return prefix + hsla.join() + ")";
16457 },
16458 toHexString: function( includeAlpha ) {
16459 var rgba = this._rgba.slice(),
16460 alpha = rgba.pop();
16461
16462 if ( includeAlpha ) {
16463 rgba.push( ~~( alpha * 255 ) );
16464 }
16465
16466 return "#" + jQuery.map( rgba, function( v ) {
16467
16468 // default to 0 when nulls exist
16469 v = ( v || 0 ).toString( 16 );
16470 return v.length === 1 ? "0" + v : v;
16471 }).join("");
16472 },
16473 toString: function() {
16474 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
16475 }
16476 });
16477 color.fn.parse.prototype = color.fn;
16478
16479 // hsla conversions adapted from:
16480 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
16481
16482 function hue2rgb( p, q, h ) {
16483 h = ( h + 1 ) % 1;
16484 if ( h * 6 < 1 ) {
16485 return p + (q - p) * h * 6;
16486 }
16487 if ( h * 2 < 1) {
16488 return q;
16489 }
16490 if ( h * 3 < 2 ) {
16491 return p + (q - p) * ((2/3) - h) * 6;
16492 }
16493 return p;
16494 }
16495
16496 spaces.hsla.to = function ( rgba ) {
16497 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
16498 return [ null, null, null, rgba[ 3 ] ];
16499 }
16500 var r = rgba[ 0 ] / 255,
16501 g = rgba[ 1 ] / 255,
16502 b = rgba[ 2 ] / 255,
16503 a = rgba[ 3 ],
16504 max = Math.max( r, g, b ),
16505 min = Math.min( r, g, b ),
16506 diff = max - min,
16507 add = max + min,
16508 l = add * 0.5,
16509 h, s;
16510
16511 if ( min === max ) {
16512 h = 0;
16513 } else if ( r === max ) {
16514 h = ( 60 * ( g - b ) / diff ) + 360;
16515 } else if ( g === max ) {
16516 h = ( 60 * ( b - r ) / diff ) + 120;
16517 } else {
16518 h = ( 60 * ( r - g ) / diff ) + 240;
16519 }
16520
16521 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
16522 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
16523 if ( diff === 0 ) {
16524 s = 0;
16525 } else if ( l <= 0.5 ) {
16526 s = diff / add;
16527 } else {
16528 s = diff / ( 2 - add );
16529 }
16530 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
16531 };
16532
16533 spaces.hsla.from = function ( hsla ) {
16534 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
16535 return [ null, null, null, hsla[ 3 ] ];
16536 }
16537 var h = hsla[ 0 ] / 360,
16538 s = hsla[ 1 ],
16539 l = hsla[ 2 ],
16540 a = hsla[ 3 ],
16541 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
16542 p = 2 * l - q;
16543
16544 return [
16545 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
16546 Math.round( hue2rgb( p, q, h ) * 255 ),
16547 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
16548 a
16549 ];
16550 };
16551
16552
16553 each( spaces, function( spaceName, space ) {
16554 var props = space.props,
16555 cache = space.cache,
16556 to = space.to,
16557 from = space.from;
16558
16559 // makes rgba() and hsla()
16560 color.fn[ spaceName ] = function( value ) {
16561
16562 // generate a cache for this space if it doesn't exist
16563 if ( to && !this[ cache ] ) {
16564 this[ cache ] = to( this._rgba );
16565 }
16566 if ( value === undefined ) {
16567 return this[ cache ].slice();
16568 }
16569
16570 var ret,
16571 type = jQuery.type( value ),
16572 arr = ( type === "array" || type === "object" ) ? value : arguments,
16573 local = this[ cache ].slice();
16574
16575 each( props, function( key, prop ) {
16576 var val = arr[ type === "object" ? key : prop.idx ];
16577 if ( val == null ) {
16578 val = local[ prop.idx ];
16579 }
16580 local[ prop.idx ] = clamp( val, prop );
16581 });
16582
16583 if ( from ) {
16584 ret = color( from( local ) );
16585 ret[ cache ] = local;
16586 return ret;
16587 } else {
16588 return color( local );
16589 }
16590 };
16591
16592 // makes red() green() blue() alpha() hue() saturation() lightness()
16593 each( props, function( key, prop ) {
16594 // alpha is included in more than one space
16595 if ( color.fn[ key ] ) {
16596 return;
16597 }
16598 color.fn[ key ] = function( value ) {
16599 var vtype = jQuery.type( value ),
16600 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
16601 local = this[ fn ](),
16602 cur = local[ prop.idx ],
16603 match;
16604
16605 if ( vtype === "undefined" ) {
16606 return cur;
16607 }
16608
16609 if ( vtype === "function" ) {
16610 value = value.call( this, cur );
16611 vtype = jQuery.type( value );
16612 }
16613 if ( value == null && prop.empty ) {
16614 return this;
16615 }
16616 if ( vtype === "string" ) {
16617 match = rplusequals.exec( value );
16618 if ( match ) {
16619 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
16620 }
16621 }
16622 local[ prop.idx ] = value;
16623 return this[ fn ]( local );
16624 };
16625 });
16626 });
16627
16628 // add cssHook and .fx.step function for each named hook.
16629 // accept a space separated string of properties
16630 color.hook = function( hook ) {
16631 var hooks = hook.split( " " );
16632 each( hooks, function( i, hook ) {
16633 jQuery.cssHooks[ hook ] = {
16634 set: function( elem, value ) {
16635 var parsed, curElem,
16636 backgroundColor = "";
16637
16638 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
16639 value = color( parsed || value );
16640 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
16641 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
16642 while (
16643 (backgroundColor === "" || backgroundColor === "transparent") &&
16644 curElem && curElem.style
16645 ) {
16646 try {
16647 backgroundColor = jQuery.css( curElem, "backgroundColor" );
16648 curElem = curElem.parentNode;
16649 } catch ( e ) {
16650 }
16651 }
16652
16653 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
16654 backgroundColor :
16655 "_default" );
16656 }
16657
16658 value = value.toRgbaString();
16659 }
16660 try {
16661 elem.style[ hook ] = value;
16662 } catch( e ) {
16663 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
16664 }
16665 }
16666 };
16667 jQuery.fx.step[ hook ] = function( fx ) {
16668 if ( !fx.colorInit ) {
16669 fx.start = color( fx.elem, hook );
16670 fx.end = color( fx.end );
16671 fx.colorInit = true;
16672 }
16673 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
16674 };
16675 });
16676
16677 };
16678
16679 color.hook( stepHooks );
16680
16681 jQuery.cssHooks.borderColor = {
16682 expand: function( value ) {
16683 var expanded = {};
16684
16685 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
16686 expanded[ "border" + part + "Color" ] = value;
16687 });
16688 return expanded;
16689 }
16690 };
16691
16692 // Basic color names only.
16693 // Usage of any of the other color names requires adding yourself or including
16694 // jquery.color.svg-names.js.
16695 colors = jQuery.Color.names = {
16696 // 4.1. Basic color keywords
16697 aqua: "#00ffff",
16698 black: "#000000",
16699 blue: "#0000ff",
16700 fuchsia: "#ff00ff",
16701 gray: "#808080",
16702 green: "#008000",
16703 lime: "#00ff00",
16704 maroon: "#800000",
16705 navy: "#000080",
16706 olive: "#808000",
16707 purple: "#800080",
16708 red: "#ff0000",
16709 silver: "#c0c0c0",
16710 teal: "#008080",
16711 white: "#ffffff",
16712 yellow: "#ffff00",
16713
16714 // 4.2.3. "transparent" color keyword
16715 transparent: [ null, null, null, 0 ],
16716
16717 _default: "#ffffff"
16718 };
16719
16720 })( jQuery );
16721
16722
16723 /******************************************************************************/
16724 /****************************** CLASS ANIMATIONS ******************************/
16725 /******************************************************************************/
16726 (function() {
16727
16728 var classAnimationActions = [ "add", "remove", "toggle" ],
16729 shorthandStyles = {
16730 border: 1,
16731 borderBottom: 1,
16732 borderColor: 1,
16733 borderLeft: 1,
16734 borderRight: 1,
16735 borderTop: 1,
16736 borderWidth: 1,
16737 margin: 1,
16738 padding: 1
16739 };
16740
16741 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
16742 $.fx.step[ prop ] = function( fx ) {
16743 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
16744 jQuery.style( fx.elem, prop, fx.end );
16745 fx.setAttr = true;
16746 }
16747 };
16748 });
16749
16750 function getElementStyles( elem ) {
16751 var key, len,
16752 style = elem.ownerDocument.defaultView ?
16753 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
16754 elem.currentStyle,
16755 styles = {};
16756
16757 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
16758 len = style.length;
16759 while ( len-- ) {
16760 key = style[ len ];
16761 if ( typeof style[ key ] === "string" ) {
16762 styles[ $.camelCase( key ) ] = style[ key ];
16763 }
16764 }
16765 // support: Opera, IE <9
16766 } else {
16767 for ( key in style ) {
16768 if ( typeof style[ key ] === "string" ) {
16769 styles[ key ] = style[ key ];
16770 }
16771 }
16772 }
16773
16774 return styles;
16775 }
16776
16777
16778 function styleDifference( oldStyle, newStyle ) {
16779 var diff = {},
16780 name, value;
16781
16782 for ( name in newStyle ) {
16783 value = newStyle[ name ];
16784 if ( oldStyle[ name ] !== value ) {
16785 if ( !shorthandStyles[ name ] ) {
16786 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
16787 diff[ name ] = value;
16788 }
16789 }
16790 }
16791 }
16792
16793 return diff;
16794 }
16795
16796 // support: jQuery <1.8
16797 if ( !$.fn.addBack ) {
16798 $.fn.addBack = function( selector ) {
16799 return this.add( selector == null ?
16800 this.prevObject : this.prevObject.filter( selector )
16801 );
16802 };
16803 }
16804
16805 $.effects.animateClass = function( value, duration, easing, callback ) {
16806 var o = $.speed( duration, easing, callback );
16807
16808 return this.queue( function() {
16809 var animated = $( this ),
16810 baseClass = animated.attr( "class" ) || "",
16811 applyClassChange,
16812 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
16813
16814 // map the animated objects to store the original styles.
16815 allAnimations = allAnimations.map(function() {
16816 var el = $( this );
16817 return {
16818 el: el,
16819 start: getElementStyles( this )
16820 };
16821 });
16822
16823 // apply class change
16824 applyClassChange = function() {
16825 $.each( classAnimationActions, function(i, action) {
16826 if ( value[ action ] ) {
16827 animated[ action + "Class" ]( value[ action ] );
16828 }
16829 });
16830 };
16831 applyClassChange();
16832
16833 // map all animated objects again - calculate new styles and diff
16834 allAnimations = allAnimations.map(function() {
16835 this.end = getElementStyles( this.el[ 0 ] );
16836 this.diff = styleDifference( this.start, this.end );
16837 return this;
16838 });
16839
16840 // apply original class
16841 animated.attr( "class", baseClass );
16842
16843 // map all animated objects again - this time collecting a promise
16844 allAnimations = allAnimations.map(function() {
16845 var styleInfo = this,
16846 dfd = $.Deferred(),
16847 opts = $.extend({}, o, {
16848 queue: false,
16849 complete: function() {
16850 dfd.resolve( styleInfo );
16851 }
16852 });
16853
16854 this.el.animate( this.diff, opts );
16855 return dfd.promise();
16856 });
16857
16858 // once all animations have completed:
16859 $.when.apply( $, allAnimations.get() ).done(function() {
16860
16861 // set the final class
16862 applyClassChange();
16863
16864 // for each animated element,
16865 // clear all css properties that were animated
16866 $.each( arguments, function() {
16867 var el = this.el;
16868 $.each( this.diff, function(key) {
16869 el.css( key, "" );
16870 });
16871 });
16872
16873 // this is guarnteed to be there if you use jQuery.speed()
16874 // it also handles dequeuing the next anim...
16875 o.complete.call( animated[ 0 ] );
16876 });
16877 });
16878 };
16879
16880 $.fn.extend({
16881 addClass: (function( orig ) {
16882 return function( classNames, speed, easing, callback ) {
16883 return speed ?
16884 $.effects.animateClass.call( this,
16885 { add: classNames }, speed, easing, callback ) :
16886 orig.apply( this, arguments );
16887 };
16888 })( $.fn.addClass ),
16889
16890 removeClass: (function( orig ) {
16891 return function( classNames, speed, easing, callback ) {
16892 return arguments.length > 1 ?
16893 $.effects.animateClass.call( this,
16894 { remove: classNames }, speed, easing, callback ) :
16895 orig.apply( this, arguments );
16896 };
16897 })( $.fn.removeClass ),
16898
16899 toggleClass: (function( orig ) {
16900 return function( classNames, force, speed, easing, callback ) {
16901 if ( typeof force === "boolean" || force === undefined ) {
16902 if ( !speed ) {
16903 // without speed parameter
16904 return orig.apply( this, arguments );
16905 } else {
16906 return $.effects.animateClass.call( this,
16907 (force ? { add: classNames } : { remove: classNames }),
16908 speed, easing, callback );
16909 }
16910 } else {
16911 // without force parameter
16912 return $.effects.animateClass.call( this,
16913 { toggle: classNames }, force, speed, easing );
16914 }
16915 };
16916 })( $.fn.toggleClass ),
16917
16918 switchClass: function( remove, add, speed, easing, callback) {
16919 return $.effects.animateClass.call( this, {
16920 add: add,
16921 remove: remove
16922 }, speed, easing, callback );
16923 }
16924 });
16925
16926 })();
16927
16928 /******************************************************************************/
16929 /*********************************** EFFECTS **********************************/
16930 /******************************************************************************/
16931
16932 (function() {
16933
16934 $.extend( $.effects, {
16935 version: "1.10.3",
16936
16937 // Saves a set of properties in a data storage
16938 save: function( element, set ) {
16939 for( var i=0; i < set.length; i++ ) {
16940 if ( set[ i ] !== null ) {
16941 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
16942 }
16943 }
16944 },
16945
16946 // Restores a set of previously saved properties from a data storage
16947 restore: function( element, set ) {
16948 var val, i;
16949 for( i=0; i < set.length; i++ ) {
16950 if ( set[ i ] !== null ) {
16951 val = element.data( dataSpace + set[ i ] );
16952 // support: jQuery 1.6.2
16953 // http://bugs.jquery.com/ticket/9917
16954 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
16955 // We can't differentiate between "" and 0 here, so we just assume
16956 // empty string since it's likely to be a more common value...
16957 if ( val === undefined ) {
16958 val = "";
16959 }
16960 element.css( set[ i ], val );
16961 }
16962 }
16963 },
16964
16965 setMode: function( el, mode ) {
16966 if (mode === "toggle") {
16967 mode = el.is( ":hidden" ) ? "show" : "hide";
16968 }
16969 return mode;
16970 },
16971
16972 // Translates a [top,left] array into a baseline value
16973 // this should be a little more flexible in the future to handle a string & hash
16974 getBaseline: function( origin, original ) {
16975 var y, x;
16976 switch ( origin[ 0 ] ) {
16977 case "top": y = 0; break;
16978 case "middle": y = 0.5; break;
16979 case "bottom": y = 1; break;
16980 default: y = origin[ 0 ] / original.height;
16981 }
16982 switch ( origin[ 1 ] ) {
16983 case "left": x = 0; break;
16984 case "center": x = 0.5; break;
16985 case "right": x = 1; break;
16986 default: x = origin[ 1 ] / original.width;
16987 }
16988 return {
16989 x: x,
16990 y: y
16991 };
16992 },
16993
16994 // Wraps the element around a wrapper that copies position properties
16995 createWrapper: function( element ) {
16996
16997 // if the element is already wrapped, return it
16998 if ( element.parent().is( ".ui-effects-wrapper" )) {
16999 return element.parent();
17000 }
17001
17002 // wrap the element
17003 var props = {
17004 width: element.outerWidth(true),
17005 height: element.outerHeight(true),
17006 "float": element.css( "float" )
17007 },
17008 wrapper = $( "<div></div>" )
17009 .addClass( "ui-effects-wrapper" )
17010 .css({
17011 fontSize: "100%",
17012 background: "transparent",
17013 border: "none",
17014 margin: 0,
17015 padding: 0
17016 }),
17017 // Store the size in case width/height are defined in % - Fixes #5245
17018 size = {
17019 width: element.width(),
17020 height: element.height()
17021 },
17022 active = document.activeElement;
17023
17024 // support: Firefox
17025 // Firefox incorrectly exposes anonymous content
17026 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
17027 try {
17028 active.id;
17029 } catch( e ) {
17030 active = document.body;
17031 }
17032
17033 element.wrap( wrapper );
17034
17035 // Fixes #7595 - Elements lose focus when wrapped.
17036 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
17037 $( active ).focus();
17038 }
17039
17040 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
17041
17042 // transfer positioning properties to the wrapper
17043 if ( element.css( "position" ) === "static" ) {
17044 wrapper.css({ position: "relative" });
17045 element.css({ position: "relative" });
17046 } else {
17047 $.extend( props, {
17048 position: element.css( "position" ),
17049 zIndex: element.css( "z-index" )
17050 });
17051 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
17052 props[ pos ] = element.css( pos );
17053 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
17054 props[ pos ] = "auto";
17055 }
17056 });
17057 element.css({
17058 position: "relative",
17059 top: 0,
17060 left: 0,
17061 right: "auto",
17062 bottom: "auto"
17063 });
17064 }
17065 element.css(size);
17066
17067 return wrapper.css( props ).show();
17068 },
17069
17070 removeWrapper: function( element ) {
17071 var active = document.activeElement;
17072
17073 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
17074 element.parent().replaceWith( element );
17075
17076 // Fixes #7595 - Elements lose focus when wrapped.
17077 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
17078 $( active ).focus();
17079 }
17080 }
17081
17082
17083 return element;
17084 },
17085
17086 setTransition: function( element, list, factor, value ) {
17087 value = value || {};
17088 $.each( list, function( i, x ) {
17089 var unit = element.cssUnit( x );
17090 if ( unit[ 0 ] > 0 ) {
17091 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
17092 }
17093 });
17094 return value;
17095 }
17096 });
17097
17098 // return an effect options object for the given parameters:
17099 function _normalizeArguments( effect, options, speed, callback ) {
17100
17101 // allow passing all options as the first parameter
17102 if ( $.isPlainObject( effect ) ) {
17103 options = effect;
17104 effect = effect.effect;
17105 }
17106
17107 // convert to an object
17108 effect = { effect: effect };
17109
17110 // catch (effect, null, ...)
17111 if ( options == null ) {
17112 options = {};
17113 }
17114
17115 // catch (effect, callback)
17116 if ( $.isFunction( options ) ) {
17117 callback = options;
17118 speed = null;
17119 options = {};
17120 }
17121
17122 // catch (effect, speed, ?)
17123 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
17124 callback = speed;
17125 speed = options;
17126 options = {};
17127 }
17128
17129 // catch (effect, options, callback)
17130 if ( $.isFunction( speed ) ) {
17131 callback = speed;
17132 speed = null;
17133 }
17134
17135 // add options to effect
17136 if ( options ) {
17137 $.extend( effect, options );
17138 }
17139
17140 speed = speed || options.duration;
17141 effect.duration = $.fx.off ? 0 :
17142 typeof speed === "number" ? speed :
17143 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
17144 $.fx.speeds._default;
17145
17146 effect.complete = callback || options.complete;
17147
17148 return effect;
17149 }
17150
17151 function standardAnimationOption( option ) {
17152 // Valid standard speeds (nothing, number, named speed)
17153 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
17154 return true;
17155 }
17156
17157 // Invalid strings - treat as "normal" speed
17158 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
17159 return true;
17160 }
17161
17162 // Complete callback
17163 if ( $.isFunction( option ) ) {
17164 return true;
17165 }
17166
17167 // Options hash (but not naming an effect)
17168 if ( typeof option === "object" && !option.effect ) {
17169 return true;
17170 }
17171
17172 // Didn't match any standard API
17173 return false;
17174 }
17175
17176 $.fn.extend({
17177 effect: function( /* effect, options, speed, callback */ ) {
17178 var args = _normalizeArguments.apply( this, arguments ),
17179 mode = args.mode,
17180 queue = args.queue,
17181 effectMethod = $.effects.effect[ args.effect ];
17182
17183 if ( $.fx.off || !effectMethod ) {
17184 // delegate to the original method (e.g., .show()) if possible
17185 if ( mode ) {
17186 return this[ mode ]( args.duration, args.complete );
17187 } else {
17188 return this.each( function() {
17189 if ( args.complete ) {
17190 args.complete.call( this );
17191 }
17192 });
17193 }
17194 }
17195
17196 function run( next ) {
17197 var elem = $( this ),
17198 complete = args.complete,
17199 mode = args.mode;
17200
17201 function done() {
17202 if ( $.isFunction( complete ) ) {
17203 complete.call( elem[0] );
17204 }
17205 if ( $.isFunction( next ) ) {
17206 next();
17207 }
17208 }
17209
17210 // If the element already has the correct final state, delegate to
17211 // the core methods so the internal tracking of "olddisplay" works.
17212 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
17213 elem[ mode ]();
17214 done();
17215 } else {
17216 effectMethod.call( elem[0], args, done );
17217 }
17218 }
17219
17220 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
17221 },
17222
17223 show: (function( orig ) {
17224 return function( option ) {
17225 if ( standardAnimationOption( option ) ) {
17226 return orig.apply( this, arguments );
17227 } else {
17228 var args = _normalizeArguments.apply( this, arguments );
17229 args.mode = "show";
17230 return this.effect.call( this, args );
17231 }
17232 };
17233 })( $.fn.show ),
17234
17235 hide: (function( orig ) {
17236 return function( option ) {
17237 if ( standardAnimationOption( option ) ) {
17238 return orig.apply( this, arguments );
17239 } else {
17240 var args = _normalizeArguments.apply( this, arguments );
17241 args.mode = "hide";
17242 return this.effect.call( this, args );
17243 }
17244 };
17245 })( $.fn.hide ),
17246
17247 toggle: (function( orig ) {
17248 return function( option ) {
17249 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
17250 return orig.apply( this, arguments );
17251 } else {
17252 var args = _normalizeArguments.apply( this, arguments );
17253 args.mode = "toggle";
17254 return this.effect.call( this, args );
17255 }
17256 };
17257 })( $.fn.toggle ),
17258
17259 // helper functions
17260 cssUnit: function(key) {
17261 var style = this.css( key ),
17262 val = [];
17263
17264 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
17265 if ( style.indexOf( unit ) > 0 ) {
17266 val = [ parseFloat( style ), unit ];
17267 }
17268 });
17269 return val;
17270 }
17271 });
17272
17273 })();
17274
17275 /******************************************************************************/
17276 /*********************************** EASING ***********************************/
17277 /******************************************************************************/
17278
17279 (function() {
17280
17281 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
17282
17283 var baseEasings = {};
17284
17285 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
17286 baseEasings[ name ] = function( p ) {
17287 return Math.pow( p, i + 2 );
17288 };
17289 });
17290
17291 $.extend( baseEasings, {
17292 Sine: function ( p ) {
17293 return 1 - Math.cos( p * Math.PI / 2 );
17294 },
17295 Circ: function ( p ) {
17296 return 1 - Math.sqrt( 1 - p * p );
17297 },
17298 Elastic: function( p ) {
17299 return p === 0 || p === 1 ? p :
17300 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
17301 },
17302 Back: function( p ) {
17303 return p * p * ( 3 * p - 2 );
17304 },
17305 Bounce: function ( p ) {
17306 var pow2,
17307 bounce = 4;
17308
17309 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
17310 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
17311 }
17312 });
17313
17314 $.each( baseEasings, function( name, easeIn ) {
17315 $.easing[ "easeIn" + name ] = easeIn;
17316 $.easing[ "easeOut" + name ] = function( p ) {
17317 return 1 - easeIn( 1 - p );
17318 };
17319 $.easing[ "easeInOut" + name ] = function( p ) {
17320 return p < 0.5 ?
17321 easeIn( p * 2 ) / 2 :
17322 1 - easeIn( p * -2 + 2 ) / 2;
17323 };
17324 });
17325
17326 })();
17327
17328 })(jQuery);
17329 (function( $, undefined ) {
17330
17331 var rvertical = /up|down|vertical/,
17332 rpositivemotion = /up|left|vertical|horizontal/;
17333
17334 $.effects.effect.blind = function( o, done ) {
17335 // Create element
17336 var el = $( this ),
17337 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
17338 mode = $.effects.setMode( el, o.mode || "hide" ),
17339 direction = o.direction || "up",
17340 vertical = rvertical.test( direction ),
17341 ref = vertical ? "height" : "width",
17342 ref2 = vertical ? "top" : "left",
17343 motion = rpositivemotion.test( direction ),
17344 animation = {},
17345 show = mode === "show",
17346 wrapper, distance, margin;
17347
17348 // if already wrapped, the wrapper's properties are my property. #6245
17349 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
17350 $.effects.save( el.parent(), props );
17351 } else {
17352 $.effects.save( el, props );
17353 }
17354 el.show();
17355 wrapper = $.effects.createWrapper( el ).css({
17356 overflow: "hidden"
17357 });
17358
17359 distance = wrapper[ ref ]();
17360 margin = parseFloat( wrapper.css( ref2 ) ) || 0;
17361
17362 animation[ ref ] = show ? distance : 0;
17363 if ( !motion ) {
17364 el
17365 .css( vertical ? "bottom" : "right", 0 )
17366 .css( vertical ? "top" : "left", "auto" )
17367 .css({ position: "absolute" });
17368
17369 animation[ ref2 ] = show ? margin : distance + margin;
17370 }
17371
17372 // start at 0 if we are showing
17373 if ( show ) {
17374 wrapper.css( ref, 0 );
17375 if ( ! motion ) {
17376 wrapper.css( ref2, margin + distance );
17377 }
17378 }
17379
17380 // Animate
17381 wrapper.animate( animation, {
17382 duration: o.duration,
17383 easing: o.easing,
17384 queue: false,
17385 complete: function() {
17386 if ( mode === "hide" ) {
17387 el.hide();
17388 }
17389 $.effects.restore( el, props );
17390 $.effects.removeWrapper( el );
17391 done();
17392 }
17393 });
17394
17395 };
17396
17397 })(jQuery);
17398 (function( $, undefined ) {
17399
17400 $.effects.effect.bounce = function( o, done ) {
17401 var el = $( this ),
17402 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
17403
17404 // defaults:
17405 mode = $.effects.setMode( el, o.mode || "effect" ),
17406 hide = mode === "hide",
17407 show = mode === "show",
17408 direction = o.direction || "up",
17409 distance = o.distance,
17410 times = o.times || 5,
17411
17412 // number of internal animations
17413 anims = times * 2 + ( show || hide ? 1 : 0 ),
17414 speed = o.duration / anims,
17415 easing = o.easing,
17416
17417 // utility:
17418 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
17419 motion = ( direction === "up" || direction === "left" ),
17420 i,
17421 upAnim,
17422 downAnim,
17423
17424 // we will need to re-assemble the queue to stack our animations in place
17425 queue = el.queue(),
17426 queuelen = queue.length;
17427
17428 // Avoid touching opacity to prevent clearType and PNG issues in IE
17429 if ( show || hide ) {
17430 props.push( "opacity" );
17431 }
17432
17433 $.effects.save( el, props );
17434 el.show();
17435 $.effects.createWrapper( el ); // Create Wrapper
17436
17437 // default distance for the BIGGEST bounce is the outer Distance / 3
17438 if ( !distance ) {
17439 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
17440 }
17441
17442 if ( show ) {
17443 downAnim = { opacity: 1 };
17444 downAnim[ ref ] = 0;
17445
17446 // if we are showing, force opacity 0 and set the initial position
17447 // then do the "first" animation
17448 el.css( "opacity", 0 )
17449 .css( ref, motion ? -distance * 2 : distance * 2 )
17450 .animate( downAnim, speed, easing );
17451 }
17452
17453 // start at the smallest distance if we are hiding
17454 if ( hide ) {
17455 distance = distance / Math.pow( 2, times - 1 );
17456 }
17457
17458 downAnim = {};
17459 downAnim[ ref ] = 0;
17460 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
17461 for ( i = 0; i < times; i++ ) {
17462 upAnim = {};
17463 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
17464
17465 el.animate( upAnim, speed, easing )
17466 .animate( downAnim, speed, easing );
17467
17468 distance = hide ? distance * 2 : distance / 2;
17469 }
17470
17471 // Last Bounce when Hiding
17472 if ( hide ) {
17473 upAnim = { opacity: 0 };
17474 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
17475
17476 el.animate( upAnim, speed, easing );
17477 }
17478
17479 el.queue(function() {
17480 if ( hide ) {
17481 el.hide();
17482 }
17483 $.effects.restore( el, props );
17484 $.effects.removeWrapper( el );
17485 done();
17486 });
17487
17488 // inject all the animations we just queued to be first in line (after "inprogress")
17489 if ( queuelen > 1) {
17490 queue.splice.apply( queue,
17491 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
17492 }
17493 el.dequeue();
17494
17495 };
17496
17497 })(jQuery);
17498 (function( $, undefined ) {
17499
17500 $.effects.effect.clip = function( o, done ) {
17501 // Create element
17502 var el = $( this ),
17503 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
17504 mode = $.effects.setMode( el, o.mode || "hide" ),
17505 show = mode === "show",
17506 direction = o.direction || "vertical",
17507 vert = direction === "vertical",
17508 size = vert ? "height" : "width",
17509 position = vert ? "top" : "left",
17510 animation = {},
17511 wrapper, animate, distance;
17512
17513 // Save & Show
17514 $.effects.save( el, props );
17515 el.show();
17516
17517 // Create Wrapper
17518 wrapper = $.effects.createWrapper( el ).css({
17519 overflow: "hidden"
17520 });
17521 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
17522 distance = animate[ size ]();
17523
17524 // Shift
17525 if ( show ) {
17526 animate.css( size, 0 );
17527 animate.css( position, distance / 2 );
17528 }
17529
17530 // Create Animation Object:
17531 animation[ size ] = show ? distance : 0;
17532 animation[ position ] = show ? 0 : distance / 2;
17533
17534 // Animate
17535 animate.animate( animation, {
17536 queue: false,
17537 duration: o.duration,
17538 easing: o.easing,
17539 complete: function() {
17540 if ( !show ) {
17541 el.hide();
17542 }
17543 $.effects.restore( el, props );
17544 $.effects.removeWrapper( el );
17545 done();
17546 }
17547 });
17548
17549 };
17550
17551 })(jQuery);
17552 (function( $, undefined ) {
17553
17554 $.effects.effect.drop = function( o, done ) {
17555
17556 var el = $( this ),
17557 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
17558 mode = $.effects.setMode( el, o.mode || "hide" ),
17559 show = mode === "show",
17560 direction = o.direction || "left",
17561 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
17562 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
17563 animation = {
17564 opacity: show ? 1 : 0
17565 },
17566 distance;
17567
17568 // Adjust
17569 $.effects.save( el, props );
17570 el.show();
17571 $.effects.createWrapper( el );
17572
17573 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
17574
17575 if ( show ) {
17576 el
17577 .css( "opacity", 0 )
17578 .css( ref, motion === "pos" ? -distance : distance );
17579 }
17580
17581 // Animation
17582 animation[ ref ] = ( show ?
17583 ( motion === "pos" ? "+=" : "-=" ) :
17584 ( motion === "pos" ? "-=" : "+=" ) ) +
17585 distance;
17586
17587 // Animate
17588 el.animate( animation, {
17589 queue: false,
17590 duration: o.duration,
17591 easing: o.easing,
17592 complete: function() {
17593 if ( mode === "hide" ) {
17594 el.hide();
17595 }
17596 $.effects.restore( el, props );
17597 $.effects.removeWrapper( el );
17598 done();
17599 }
17600 });
17601 };
17602
17603 })(jQuery);
17604 (function( $, undefined ) {
17605
17606 $.effects.effect.explode = function( o, done ) {
17607
17608 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
17609 cells = rows,
17610 el = $( this ),
17611 mode = $.effects.setMode( el, o.mode || "hide" ),
17612 show = mode === "show",
17613
17614 // show and then visibility:hidden the element before calculating offset
17615 offset = el.show().css( "visibility", "hidden" ).offset(),
17616
17617 // width and height of a piece
17618 width = Math.ceil( el.outerWidth() / cells ),
17619 height = Math.ceil( el.outerHeight() / rows ),
17620 pieces = [],
17621
17622 // loop
17623 i, j, left, top, mx, my;
17624
17625 // children animate complete:
17626 function childComplete() {
17627 pieces.push( this );
17628 if ( pieces.length === rows * cells ) {
17629 animComplete();
17630 }
17631 }
17632
17633 // clone the element for each row and cell.
17634 for( i = 0; i < rows ; i++ ) { // ===>
17635 top = offset.top + i * height;
17636 my = i - ( rows - 1 ) / 2 ;
17637
17638 for( j = 0; j < cells ; j++ ) { // |||
17639 left = offset.left + j * width;
17640 mx = j - ( cells - 1 ) / 2 ;
17641
17642 // Create a clone of the now hidden main element that will be absolute positioned
17643 // within a wrapper div off the -left and -top equal to size of our pieces
17644 el
17645 .clone()
17646 .appendTo( "body" )
17647 .wrap( "<div></div>" )
17648 .css({
17649 position: "absolute",
17650 visibility: "visible",
17651 left: -j * width,
17652 top: -i * height
17653 })
17654
17655 // select the wrapper - make it overflow: hidden and absolute positioned based on
17656 // where the original was located +left and +top equal to the size of pieces
17657 .parent()
17658 .addClass( "ui-effects-explode" )
17659 .css({
17660 position: "absolute",
17661 overflow: "hidden",
17662 width: width,
17663 height: height,
17664 left: left + ( show ? mx * width : 0 ),
17665 top: top + ( show ? my * height : 0 ),
17666 opacity: show ? 0 : 1
17667 }).animate({
17668 left: left + ( show ? 0 : mx * width ),
17669 top: top + ( show ? 0 : my * height ),
17670 opacity: show ? 1 : 0
17671 }, o.duration || 500, o.easing, childComplete );
17672 }
17673 }
17674
17675 function animComplete() {
17676 el.css({
17677 visibility: "visible"
17678 });
17679 $( pieces ).remove();
17680 if ( !show ) {
17681 el.hide();
17682 }
17683 done();
17684 }
17685 };
17686
17687 })(jQuery);
17688 (function( $, undefined ) {
17689
17690 $.effects.effect.fade = function( o, done ) {
17691 var el = $( this ),
17692 mode = $.effects.setMode( el, o.mode || "toggle" );
17693
17694 el.animate({
17695 opacity: mode
17696 }, {
17697 queue: false,
17698 duration: o.duration,
17699 easing: o.easing,
17700 complete: done
17701 });
17702 };
17703
17704 })( jQuery );
17705 (function( $, undefined ) {
17706
17707 $.effects.effect.fold = function( o, done ) {
17708
17709 // Create element
17710 var el = $( this ),
17711 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
17712 mode = $.effects.setMode( el, o.mode || "hide" ),
17713 show = mode === "show",
17714 hide = mode === "hide",
17715 size = o.size || 15,
17716 percent = /([0-9]+)%/.exec( size ),
17717 horizFirst = !!o.horizFirst,
17718 widthFirst = show !== horizFirst,
17719 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
17720 duration = o.duration / 2,
17721 wrapper, distance,
17722 animation1 = {},
17723 animation2 = {};
17724
17725 $.effects.save( el, props );
17726 el.show();
17727
17728 // Create Wrapper
17729 wrapper = $.effects.createWrapper( el ).css({
17730 overflow: "hidden"
17731 });
17732 distance = widthFirst ?
17733 [ wrapper.width(), wrapper.height() ] :
17734 [ wrapper.height(), wrapper.width() ];
17735
17736 if ( percent ) {
17737 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
17738 }
17739 if ( show ) {
17740 wrapper.css( horizFirst ? {
17741 height: 0,
17742 width: size
17743 } : {
17744 height: size,
17745 width: 0
17746 });
17747 }
17748
17749 // Animation
17750 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
17751 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
17752
17753 // Animate
17754 wrapper
17755 .animate( animation1, duration, o.easing )
17756 .animate( animation2, duration, o.easing, function() {
17757 if ( hide ) {
17758 el.hide();
17759 }
17760 $.effects.restore( el, props );
17761 $.effects.removeWrapper( el );
17762 done();
17763 });
17764
17765 };
17766
17767 })(jQuery);
17768 (function( $, undefined ) {
17769
17770 $.effects.effect.highlight = function( o, done ) {
17771 var elem = $( this ),
17772 props = [ "backgroundImage", "backgroundColor", "opacity" ],
17773 mode = $.effects.setMode( elem, o.mode || "show" ),
17774 animation = {
17775 backgroundColor: elem.css( "backgroundColor" )
17776 };
17777
17778 if (mode === "hide") {
17779 animation.opacity = 0;
17780 }
17781
17782 $.effects.save( elem, props );
17783
17784 elem
17785 .show()
17786 .css({
17787 backgroundImage: "none",
17788 backgroundColor: o.color || "#ffff99"
17789 })
17790 .animate( animation, {
17791 queue: false,
17792 duration: o.duration,
17793 easing: o.easing,
17794 complete: function() {
17795 if ( mode === "hide" ) {
17796 elem.hide();
17797 }
17798 $.effects.restore( elem, props );
17799 done();
17800 }
17801 });
17802 };
17803
17804 })(jQuery);
17805 (function( $, undefined ) {
17806
17807 $.effects.effect.pulsate = function( o, done ) {
17808 var elem = $( this ),
17809 mode = $.effects.setMode( elem, o.mode || "show" ),
17810 show = mode === "show",
17811 hide = mode === "hide",
17812 showhide = ( show || mode === "hide" ),
17813
17814 // showing or hiding leaves of the "last" animation
17815 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
17816 duration = o.duration / anims,
17817 animateTo = 0,
17818 queue = elem.queue(),
17819 queuelen = queue.length,
17820 i;
17821
17822 if ( show || !elem.is(":visible")) {
17823 elem.css( "opacity", 0 ).show();
17824 animateTo = 1;
17825 }
17826
17827 // anims - 1 opacity "toggles"
17828 for ( i = 1; i < anims; i++ ) {
17829 elem.animate({
17830 opacity: animateTo
17831 }, duration, o.easing );
17832 animateTo = 1 - animateTo;
17833 }
17834
17835 elem.animate({
17836 opacity: animateTo
17837 }, duration, o.easing);
17838
17839 elem.queue(function() {
17840 if ( hide ) {
17841 elem.hide();
17842 }
17843 done();
17844 });
17845
17846 // We just queued up "anims" animations, we need to put them next in the queue
17847 if ( queuelen > 1 ) {
17848 queue.splice.apply( queue,
17849 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
17850 }
17851 elem.dequeue();
17852 };
17853
17854 })(jQuery);
17855 (function( $, undefined ) {
17856
17857 $.effects.effect.puff = function( o, done ) {
17858 var elem = $( this ),
17859 mode = $.effects.setMode( elem, o.mode || "hide" ),
17860 hide = mode === "hide",
17861 percent = parseInt( o.percent, 10 ) || 150,
17862 factor = percent / 100,
17863 original = {
17864 height: elem.height(),
17865 width: elem.width(),
17866 outerHeight: elem.outerHeight(),
17867 outerWidth: elem.outerWidth()
17868 };
17869
17870 $.extend( o, {
17871 effect: "scale",
17872 queue: false,
17873 fade: true,
17874 mode: mode,
17875 complete: done,
17876 percent: hide ? percent : 100,
17877 from: hide ?
17878 original :
17879 {
17880 height: original.height * factor,
17881 width: original.width * factor,
17882 outerHeight: original.outerHeight * factor,
17883 outerWidth: original.outerWidth * factor
17884 }
17885 });
17886
17887 elem.effect( o );
17888 };
17889
17890 $.effects.effect.scale = function( o, done ) {
17891
17892 // Create element
17893 var el = $( this ),
17894 options = $.extend( true, {}, o ),
17895 mode = $.effects.setMode( el, o.mode || "effect" ),
17896 percent = parseInt( o.percent, 10 ) ||
17897 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
17898 direction = o.direction || "both",
17899 origin = o.origin,
17900 original = {
17901 height: el.height(),
17902 width: el.width(),
17903 outerHeight: el.outerHeight(),
17904 outerWidth: el.outerWidth()
17905 },
17906 factor = {
17907 y: direction !== "horizontal" ? (percent / 100) : 1,
17908 x: direction !== "vertical" ? (percent / 100) : 1
17909 };
17910
17911 // We are going to pass this effect to the size effect:
17912 options.effect = "size";
17913 options.queue = false;
17914 options.complete = done;
17915
17916 // Set default origin and restore for show/hide
17917 if ( mode !== "effect" ) {
17918 options.origin = origin || ["middle","center"];
17919 options.restore = true;
17920 }
17921
17922 options.from = o.from || ( mode === "show" ? {
17923 height: 0,
17924 width: 0,
17925 outerHeight: 0,
17926 outerWidth: 0
17927 } : original );
17928 options.to = {
17929 height: original.height * factor.y,
17930 width: original.width * factor.x,
17931 outerHeight: original.outerHeight * factor.y,
17932 outerWidth: original.outerWidth * factor.x
17933 };
17934
17935 // Fade option to support puff
17936 if ( options.fade ) {
17937 if ( mode === "show" ) {
17938 options.from.opacity = 0;
17939 options.to.opacity = 1;
17940 }
17941 if ( mode === "hide" ) {
17942 options.from.opacity = 1;
17943 options.to.opacity = 0;
17944 }
17945 }
17946
17947 // Animate
17948 el.effect( options );
17949
17950 };
17951
17952 $.effects.effect.size = function( o, done ) {
17953
17954 // Create element
17955 var original, baseline, factor,
17956 el = $( this ),
17957 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
17958
17959 // Always restore
17960 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
17961
17962 // Copy for children
17963 props2 = [ "width", "height", "overflow" ],
17964 cProps = [ "fontSize" ],
17965 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
17966 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
17967
17968 // Set options
17969 mode = $.effects.setMode( el, o.mode || "effect" ),
17970 restore = o.restore || mode !== "effect",
17971 scale = o.scale || "both",
17972 origin = o.origin || [ "middle", "center" ],
17973 position = el.css( "position" ),
17974 props = restore ? props0 : props1,
17975 zero = {
17976 height: 0,
17977 width: 0,
17978 outerHeight: 0,
17979 outerWidth: 0
17980 };
17981
17982 if ( mode === "show" ) {
17983 el.show();
17984 }
17985 original = {
17986 height: el.height(),
17987 width: el.width(),
17988 outerHeight: el.outerHeight(),
17989 outerWidth: el.outerWidth()
17990 };
17991
17992 if ( o.mode === "toggle" && mode === "show" ) {
17993 el.from = o.to || zero;
17994 el.to = o.from || original;
17995 } else {
17996 el.from = o.from || ( mode === "show" ? zero : original );
17997 el.to = o.to || ( mode === "hide" ? zero : original );
17998 }
17999
18000 // Set scaling factor
18001 factor = {
18002 from: {
18003 y: el.from.height / original.height,
18004 x: el.from.width / original.width
18005 },
18006 to: {
18007 y: el.to.height / original.height,
18008 x: el.to.width / original.width
18009 }
18010 };
18011
18012 // Scale the css box
18013 if ( scale === "box" || scale === "both" ) {
18014
18015 // Vertical props scaling
18016 if ( factor.from.y !== factor.to.y ) {
18017 props = props.concat( vProps );
18018 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
18019 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
18020 }
18021
18022 // Horizontal props scaling
18023 if ( factor.from.x !== factor.to.x ) {
18024 props = props.concat( hProps );
18025 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
18026 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
18027 }
18028 }
18029
18030 // Scale the content
18031 if ( scale === "content" || scale === "both" ) {
18032
18033 // Vertical props scaling
18034 if ( factor.from.y !== factor.to.y ) {
18035 props = props.concat( cProps ).concat( props2 );
18036 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
18037 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
18038 }
18039 }
18040
18041 $.effects.save( el, props );
18042 el.show();
18043 $.effects.createWrapper( el );
18044 el.css( "overflow", "hidden" ).css( el.from );
18045
18046 // Adjust
18047 if (origin) { // Calculate baseline shifts
18048 baseline = $.effects.getBaseline( origin, original );
18049 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
18050 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
18051 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
18052 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
18053 }
18054 el.css( el.from ); // set top & left
18055
18056 // Animate
18057 if ( scale === "content" || scale === "both" ) { // Scale the children
18058
18059 // Add margins/font-size
18060 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
18061 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
18062 props2 = props0.concat(vProps).concat(hProps);
18063
18064 el.find( "*[width]" ).each( function(){
18065 var child = $( this ),
18066 c_original = {
18067 height: child.height(),
18068 width: child.width(),
18069 outerHeight: child.outerHeight(),
18070 outerWidth: child.outerWidth()
18071 };
18072 if (restore) {
18073 $.effects.save(child, props2);
18074 }
18075
18076 child.from = {
18077 height: c_original.height * factor.from.y,
18078 width: c_original.width * factor.from.x,
18079 outerHeight: c_original.outerHeight * factor.from.y,
18080 outerWidth: c_original.outerWidth * factor.from.x
18081 };
18082 child.to = {
18083 height: c_original.height * factor.to.y,
18084 width: c_original.width * factor.to.x,
18085 outerHeight: c_original.height * factor.to.y,
18086 outerWidth: c_original.width * factor.to.x
18087 };
18088
18089 // Vertical props scaling
18090 if ( factor.from.y !== factor.to.y ) {
18091 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
18092 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
18093 }
18094
18095 // Horizontal props scaling
18096 if ( factor.from.x !== factor.to.x ) {
18097 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
18098 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
18099 }
18100
18101 // Animate children
18102 child.css( child.from );
18103 child.animate( child.to, o.duration, o.easing, function() {
18104
18105 // Restore children
18106 if ( restore ) {
18107 $.effects.restore( child, props2 );
18108 }
18109 });
18110 });
18111 }
18112
18113 // Animate
18114 el.animate( el.to, {
18115 queue: false,
18116 duration: o.duration,
18117 easing: o.easing,
18118 complete: function() {
18119 if ( el.to.opacity === 0 ) {
18120 el.css( "opacity", el.from.opacity );
18121 }
18122 if( mode === "hide" ) {
18123 el.hide();
18124 }
18125 $.effects.restore( el, props );
18126 if ( !restore ) {
18127
18128 // we need to calculate our new positioning based on the scaling
18129 if ( position === "static" ) {
18130 el.css({
18131 position: "relative",
18132 top: el.to.top,
18133 left: el.to.left
18134 });
18135 } else {
18136 $.each([ "top", "left" ], function( idx, pos ) {
18137 el.css( pos, function( _, str ) {
18138 var val = parseInt( str, 10 ),
18139 toRef = idx ? el.to.left : el.to.top;
18140
18141 // if original was "auto", recalculate the new value from wrapper
18142 if ( str === "auto" ) {
18143 return toRef + "px";
18144 }
18145
18146 return val + toRef + "px";
18147 });
18148 });
18149 }
18150 }
18151
18152 $.effects.removeWrapper( el );
18153 done();
18154 }
18155 });
18156
18157 };
18158
18159 })(jQuery);
18160 (function( $, undefined ) {
18161
18162 $.effects.effect.shake = function( o, done ) {
18163
18164 var el = $( this ),
18165 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
18166 mode = $.effects.setMode( el, o.mode || "effect" ),
18167 direction = o.direction || "left",
18168 distance = o.distance || 20,
18169 times = o.times || 3,
18170 anims = times * 2 + 1,
18171 speed = Math.round(o.duration/anims),
18172 ref = (direction === "up" || direction === "down") ? "top" : "left",
18173 positiveMotion = (direction === "up" || direction === "left"),
18174 animation = {},
18175 animation1 = {},
18176 animation2 = {},
18177 i,
18178
18179 // we will need to re-assemble the queue to stack our animations in place
18180 queue = el.queue(),
18181 queuelen = queue.length;
18182
18183 $.effects.save( el, props );
18184 el.show();
18185 $.effects.createWrapper( el );
18186
18187 // Animation
18188 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
18189 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
18190 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
18191
18192 // Animate
18193 el.animate( animation, speed, o.easing );
18194
18195 // Shakes
18196 for ( i = 1; i < times; i++ ) {
18197 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
18198 }
18199 el
18200 .animate( animation1, speed, o.easing )
18201 .animate( animation, speed / 2, o.easing )
18202 .queue(function() {
18203 if ( mode === "hide" ) {
18204 el.hide();
18205 }
18206 $.effects.restore( el, props );
18207 $.effects.removeWrapper( el );
18208 done();
18209 });
18210
18211 // inject all the animations we just queued to be first in line (after "inprogress")
18212 if ( queuelen > 1) {
18213 queue.splice.apply( queue,
18214 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
18215 }
18216 el.dequeue();
18217
18218 };
18219
18220 })(jQuery);
18221 (function( $, undefined ) {
18222
18223 $.effects.effect.slide = function( o, done ) {
18224
18225 // Create element
18226 var el = $( this ),
18227 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
18228 mode = $.effects.setMode( el, o.mode || "show" ),
18229 show = mode === "show",
18230 direction = o.direction || "left",
18231 ref = (direction === "up" || direction === "down") ? "top" : "left",
18232 positiveMotion = (direction === "up" || direction === "left"),
18233 distance,
18234 animation = {};
18235
18236 // Adjust
18237 $.effects.save( el, props );
18238 el.show();
18239 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
18240
18241 $.effects.createWrapper( el ).css({
18242 overflow: "hidden"
18243 });
18244
18245 if ( show ) {
18246 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
18247 }
18248
18249 // Animation
18250 animation[ ref ] = ( show ?
18251 ( positiveMotion ? "+=" : "-=") :
18252 ( positiveMotion ? "-=" : "+=")) +
18253 distance;
18254
18255 // Animate
18256 el.animate( animation, {
18257 queue: false,
18258 duration: o.duration,
18259 easing: o.easing,
18260 complete: function() {
18261 if ( mode === "hide" ) {
18262 el.hide();
18263 }
18264 $.effects.restore( el, props );
18265 $.effects.removeWrapper( el );
18266 done();
18267 }
18268 });
18269 };
18270
18271 })(jQuery);
18272 (function( $, undefined ) {
18273
18274 $.effects.effect.transfer = function( o, done ) {
18275 var elem = $( this ),
18276 target = $( o.to ),
18277 targetFixed = target.css( "position" ) === "fixed",
18278 body = $("body"),
18279 fixTop = targetFixed ? body.scrollTop() : 0,
18280 fixLeft = targetFixed ? body.scrollLeft() : 0,
18281 endPosition = target.offset(),
18282 animation = {
18283 top: endPosition.top - fixTop ,
18284 left: endPosition.left - fixLeft ,
18285 height: target.innerHeight(),
18286 width: target.innerWidth()
18287 },
18288 startPosition = elem.offset(),
18289 transfer = $( "<div class='ui-effects-transfer'></div>" )
18290 .appendTo( document.body )
18291 .addClass( o.className )
18292 .css({
18293 top: startPosition.top - fixTop ,
18294 left: startPosition.left - fixLeft ,
18295 height: elem.innerHeight(),
18296 width: elem.innerWidth(),
18297 position: targetFixed ? "fixed" : "absolute"
18298 })
18299 .animate( animation, o.duration, o.easing, function() {
18300 transfer.remove();
18301 done();
18302 });
18303 };
18304
18305 })(jQuery);
18306 /*!
18307
18308 JSZip - A Javascript class for generating and reading zip files
18309 <http://stuartk.com/jszip>
18310
18311 (c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
18312 Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
18313
18314 JSZip uses the library pako released under the MIT license :
18315 https://github.com/nodeca/pako/blob/master/LICENSE
18316 */
18317 !function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?A.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",A.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),c.createFolders&&(e=w(a))&&x.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",type:"base64",comment:null}),d.checkSupport(a.type);var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=y.call(this,o,q),u=z.call(this,l,o,r,g);g+=u.fileRecord.length+r.compressedSize,j+=u.dirRecord.length,e.push(u)}var v="";v=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var w=a.type.toLowerCase();for(b="uint8array"===w||"arraybuffer"===w||"blob"===w||"nodebuffer"===w?new n(g+j+v.length):new m(g+j+v.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(v);var x=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),x);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",x));case"base64":return a.base64?h.encode(x):x;default:return x}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=A},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a){c.checkSupport("blob");try{return new Blob([a],{type:"application/zip"})}catch(b){try{var d=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,e=new d;return e.append(a),e.getBlob("application/zip")}catch(b){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a)throw new Error("Corrupted zip : can't find end of central directory");if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object");c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readString(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength),this.dir=16&this.externalFileAttributes?!0:!1},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)
18318 };s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;
18319 if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)});
18320 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
18321 if (!Object.keys) {
18322 Object.keys = (function () {
18323 var hasOwnProperty = Object.prototype.hasOwnProperty,
18324 hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
18325 dontEnums = [
18326 'toString',
18327 'toLocaleString',
18328 'valueOf',
18329 'hasOwnProperty',
18330 'isPrototypeOf',
18331 'propertyIsEnumerable',
18332 'constructor'
18333 ],
18334 dontEnumsLength = dontEnums.length;
18335
18336 return function (obj) {
18337 if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
18338
18339 var result = [];
18340
18341 for (var prop in obj) {
18342 if (hasOwnProperty.call(obj, prop)) result.push(prop);
18343 }
18344
18345 if (hasDontEnumBug) {
18346 for (var i=0; i < dontEnumsLength; i++) {
18347 if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
18348 }
18349 }
18350 return result;
18351 };
18352 })();
18353 }
18354
18355 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
18356 if (!Array.prototype.filter)
18357 {
18358 Array.prototype.filter = function(fun /*, thisp */)
18359 {
18360 "use strict";
18361
18362 if (this == null)
18363 throw new TypeError();
18364
18365 var t = Object(this);
18366 var len = t.length >>> 0;
18367 if (typeof fun != "function")
18368 throw new TypeError();
18369
18370 var res = [];
18371 var thisp = arguments[1];
18372 for (var i = 0; i < len; i++)
18373 {
18374 if (i in t)
18375 {
18376 var val = t[i]; // in case fun mutates this
18377 if (fun.call(thisp, val, i, t))
18378 res.push(val);
18379 }
18380 }
18381
18382 return res;
18383 };
18384 }
18385
18386 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
18387 if (!String.prototype.trim) {
18388 String.prototype.trim = function () {
18389 return this.replace(/^\s+|\s+$/g, '');
18390 };
18391 }
18392
18393 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
18394 if (!Array.prototype.forEach)
18395 {
18396 Array.prototype.forEach = function(fun /*, thisArg */)
18397 {
18398 "use strict";
18399
18400 if (this === void 0 || this === null)
18401 throw new TypeError();
18402
18403 var t = Object(this);
18404 var len = t.length >>> 0;
18405 if (typeof fun !== "function")
18406 throw new TypeError();
18407
18408 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
18409 for (var i = 0; i < len; i++)
18410 {
18411 if (i in t)
18412 fun.call(thisArg, t[i], i, t);
18413 }
18414 };
18415 }
18416
18417 // Production steps of ECMA-262, Edition 5, 15.4.4.19
18418 // Reference: http://es5.github.com/#x15.4.4.19
18419 if (!Array.prototype.map) {
18420 Array.prototype.map = function(callback, thisArg) {
18421
18422 var T, A, k;
18423
18424 if (this == null) {
18425 throw new TypeError(" this is null or not defined");
18426 }
18427
18428 // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
18429 var O = Object(this);
18430
18431 // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
18432 // 3. Let len be ToUint32(lenValue).
18433 var len = O.length >>> 0;
18434
18435 // 4. If IsCallable(callback) is false, throw a TypeError exception.
18436 // See: http://es5.github.com/#x9.11
18437 if (typeof callback !== "function") {
18438 throw new TypeError(callback + " is not a function");
18439 }
18440
18441 // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
18442 if (thisArg) {
18443 T = thisArg;
18444 }
18445
18446 // 6. Let A be a new array created as if by the expression new Array(len) where Array is
18447 // the standard built-in constructor with that name and len is the value of len.
18448 A = new Array(len);
18449
18450 // 7. Let k be 0
18451 k = 0;
18452
18453 // 8. Repeat, while k < len
18454 while(k < len) {
18455
18456 var kValue, mappedValue;
18457
18458 // a. Let Pk be ToString(k).
18459 // This is implicit for LHS operands of the in operator
18460 // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
18461 // This step can be combined with c
18462 // c. If kPresent is true, then
18463 if (k in O) {
18464
18465 // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
18466 kValue = O[ k ];
18467
18468 // ii. Let mappedValue be the result of calling the Call internal method of callback
18469 // with T as the this value and argument list containing kValue, k, and O.
18470 mappedValue = callback.call(T, kValue, k, O);
18471
18472 // iii. Call the DefineOwnProperty internal method of A with arguments
18473 // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
18474 // and false.
18475
18476 // In browsers that support Object.defineProperty, use the following:
18477 // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
18478
18479 // For best browser support, use the following:
18480 A[ k ] = mappedValue;
18481 }
18482 // d. Increase k by 1.
18483 k++;
18484 }
18485
18486 // 9. return A
18487 return A;
18488 };
18489 }
18490
18491 // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
18492 if (!Array.prototype.indexOf) {
18493 Array.prototype.indexOf = function (searchElement, fromIndex) {
18494 if ( this === undefined || this === null ) {
18495 throw new TypeError( '"this" is null or not defined' );
18496 }
18497
18498 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
18499
18500 fromIndex = +fromIndex || 0;
18501
18502 if (Math.abs(fromIndex) === Infinity) {
18503 fromIndex = 0;
18504 }
18505
18506 if (fromIndex < 0) {
18507 fromIndex += length;
18508 if (fromIndex < 0) {
18509 fromIndex = 0;
18510 }
18511 }
18512
18513 for (;fromIndex < length; fromIndex++) {
18514 if (this[fromIndex] === searchElement) {
18515 return fromIndex;
18516 }
18517 }
18518
18519 return -1;
18520 };
18521 }
18522 // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
18523
18524 if (! Array.isArray) {
18525 Array.isArray = function(obj) {
18526 return Object.prototype.toString.call(obj) === "[object Array]";
18527 };
18528 }
18529
18530 // https://github.com/ttaubert/node-arraybuffer-slice
18531 // (c) 2013 Tim Taubert <tim@timtaubert.de>
18532 // arraybuffer-slice may be freely distributed under the MIT license.
18533
18534 "use strict";
18535
18536 if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
18537 ArrayBuffer.prototype.slice = function (begin, end) {
18538 begin = (begin|0) || 0;
18539 var num = this.byteLength;
18540 end = end === (void 0) ? num : (end|0);
18541
18542 // Handle negative values.
18543 if (begin < 0) begin += num;
18544 if (end < 0) end += num;
18545
18546 if (num === 0 || begin >= num || begin >= end) {
18547 return new ArrayBuffer(0);
18548 }
18549
18550 var length = Math.min(num - begin, end - begin);
18551 var target = new ArrayBuffer(length);
18552 var targetArray = new Uint8Array(target);
18553 targetArray.set(new Uint8Array(this, begin, length));
18554 return target;
18555 };
18556 }
18557 /* xls.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
18558 var XLS={};(function make_xls(XLS){XLS.version="0.7.1";var current_codepage=1252,current_cptable;if(typeof module!=="undefined"&&typeof require!=="undefined"){if(typeof cptable==="undefined")cptable=require("./dist/cpexcel");current_cptable=cptable[current_codepage]}function reset_cp(){set_cp(1252)}function set_cp(cp){current_codepage=cp;if(typeof cptable!=="undefined")current_cptable=cptable[cp]}var _getchar=function _gc1(x){return String.fromCharCode(x)};if(typeof cptable!=="undefined")_getchar=function _gc2(x){if(current_codepage===1200)return String.fromCharCode(x);return cptable.utils.decode(current_codepage,[x&255,x>>8])[0]};var has_buf=typeof Buffer!=="undefined";function new_buf(len){return new(has_buf?Buffer:Array)(len)}var Base64=function make_b64(){var map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{decode:function b64_decode(input,utf8){var o="";var c1,c2,c3;var e1,e2,e3,e4;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var i=0;i<input.length;){e1=map.indexOf(input.charAt(i++));e2=map.indexOf(input.charAt(i++));e3=map.indexOf(input.charAt(i++));e4=map.indexOf(input.charAt(i++));c1=e1<<2|e2>>4;c2=(e2&15)<<4|e3>>2;c3=(e3&3)<<6|e4;o+=String.fromCharCode(c1);if(e3!=64){o+=String.fromCharCode(c2)}if(e4!=64){o+=String.fromCharCode(c3)}}return o}}}();function s2a(s){if(has_buf)return new Buffer(s,"binary");var w=s.split("").map(function(x){return x.charCodeAt(0)&255});return w}function readIEEE754(buf,idx,isLE,nl,ml){if(isLE===undefined)isLE=true;if(!nl)nl=8;if(!ml&&nl===8)ml=52;var e,m,el=nl*8-ml-1,eMax=(1<<el)-1,eBias=eMax>>1;var bits=-7,d=isLE?-1:1,i=isLE?nl-1:0,s=buf[idx+i];i+=d;e=s&(1<<-bits)-1;s>>>=-bits;bits+=el;for(;bits>0;e=e*256+buf[idx+i],i+=d,bits-=8);m=e&(1<<-bits)-1;e>>>=-bits;bits+=ml;for(;bits>0;m=m*256+buf[idx+i],i+=d,bits-=8);if(e===eMax)return m?NaN:(s?-1:1)*Infinity;else if(e===0)e=1-eBias;else{m=m+Math.pow(2,ml);e=e-eBias}return(s?-1:1)*m*Math.pow(2,e-ml)}var chr0=/\u0000/g,chr1=/[\u0001-\u0006]/;var __toBuffer,___toBuffer;__toBuffer=___toBuffer=function toBuffer_(bufs){var x=[];for(var i=0;i<bufs[0].length;++i){x.push.apply(x,bufs[0][i])}return x};var __utf16le,___utf16le;__utf16le=___utf16le=function utf16le_(b,s,e){var ss=[];for(var i=s;i<e;i+=2)ss.push(String.fromCharCode(__readUInt16LE(b,i)));return ss.join("")};var __hexlify,___hexlify;__hexlify=___hexlify=function hexlify_(b,s,l){return b.slice(s,s+l).map(function(x){return(x<16?"0":"")+x.toString(16)}).join("")};var __utf8,___utf8;__utf8=___utf8=function(b,s,e){var ss=[];for(var i=s;i<e;i++)ss.push(String.fromCharCode(__readUInt8(b,i)));return ss.join("")};var __lpstr,___lpstr;__lpstr=___lpstr=function lpstr_(b,i){var len=__readUInt32LE(b,i);return len>0?__utf8(b,i+4,i+4+len-1):""};var __lpwstr,___lpwstr;__lpwstr=___lpwstr=function lpwstr_(b,i){var len=2*__readUInt32LE(b,i);return len>0?__utf8(b,i+4,i+4+len-1):""};var __double,___double;__double=___double=function(b,idx){return readIEEE754(b,idx)};var bconcat=function(bufs){return[].concat.apply([],bufs)};if(typeof Buffer!=="undefined"){__utf16le=function utf16le_b(b,s,e){if(!Buffer.isBuffer(b))return ___utf16le(b,s,e);return b.toString("utf16le",s,e)};__hexlify=function(b,s,l){return Buffer.isBuffer(b)?b.toString("hex",s,s+l):___hexlify(b,s,l)};__lpstr=function lpstr_b(b,i){if(!Buffer.isBuffer(b))return ___lpstr(b,i);var len=b.readUInt32LE(i);return len>0?b.toString("utf8",i+4,i+4+len-1):""};__lpwstr=function lpwstr_b(b,i){if(!Buffer.isBuffer(b))return ___lpwstr(b,i);var len=2*b.readUInt32LE(i);return b.toString("utf16le",i+4,i+4+len-1)};__utf8=function utf8_b(s,e){return this.toString("utf8",s,e)};__toBuffer=function(bufs){return bufs[0].length>0&&Buffer.isBuffer(bufs[0][0])?Buffer.concat(bufs[0]):___toBuffer(bufs)};bconcat=function(bufs){return Buffer.isBuffer(bufs[0])?Buffer.concat(bufs):[].concat.apply([],bufs)};__double=function double_(b,i){if(Buffer.isBuffer(b))return b.readDoubleLE(i);return ___double(b,i)}}var __readUInt8=function(b,idx){return b[idx]};var __readUInt16LE=function(b,idx){return b[idx+1]*(1<<8)+b[idx]};var __readInt16LE=function(b,idx){var u=b[idx+1]*(1<<8)+b[idx];return u<32768?u:(65535-u+1)*-1};var __readUInt32LE=function(b,idx){return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]};var __readInt32LE=function(b,idx){return b[idx+3]<<24|b[idx+2]<<16|b[idx+1]<<8|b[idx]};var ___unhexlify=function(s){return s.match(/../g).map(function(x){return parseInt(x,16)})};var __unhexlify=typeof Buffer!=="undefined"?function(s){return Buffer.isBuffer(s)?new Buffer(s,"hex"):___unhexlify(s)}:___unhexlify;if(typeof cptable!=="undefined"){__utf16le=function(b,s,e){return cptable.utils.decode(1200,b.slice(s,e))};__utf8=function(b,s,e){return cptable.utils.decode(65001,b.slice(s,e))};__lpstr=function(b,i){var len=__readUInt32LE(b,i);return len>0?cptable.utils.decode(current_codepage,b.slice(i+4,i+4+len-1)):""};__lpwstr=function(b,i){var len=2*__readUInt32LE(b,i);return len>0?cptable.utils.decode(1200,b.slice(i+4,i+4+len-1)):""}}function ReadShift(size,t){var o,oI,oR,oo=[],w,vv,i,loc;switch(t){case"lpstr":o=__lpstr(this,this.l);size=5+o.length;break;case"lpwstr":o=__lpwstr(this,this.l);size=5+o.length;if(o[o.length-1]=="\x00")size+=2;break;case"cstr":size=0;o="";while((w=__readUInt8(this,this.l+size++))!==0)oo.push(_getchar(w));o=oo.join("");break;case"wstr":size=0;o="";while((w=__readUInt16LE(this,this.l+size))!==0){oo.push(_getchar(w));size+=2}size+=2;o=oo.join("");break;case"dbcs":o="";loc=this.l;for(i=0;i!=size;++i){if(this.lens&&this.lens.indexOf(loc)!==-1){w=__readUInt8(this,loc);this.l=loc+1;vv=ReadShift.call(this,size-i,w?"dbcs":"sbcs");return oo.join("")+vv}oo.push(_getchar(__readUInt16LE(this,loc)));loc+=2}o=oo.join("");size*=2;break;case"sbcs":o="";loc=this.l;for(i=0;i!=size;++i){if(this.lens&&this.lens.indexOf(loc)!==-1){w=__readUInt8(this,loc);this.l=loc+1;vv=ReadShift.call(this,size-i,w?"dbcs":"sbcs");return oo.join("")+vv}oo.push(_getchar(__readUInt8(this,loc)));loc+=1}o=oo.join("");break;case"utf8":o=__utf8(this,this.l,this.l+size);break;case"utf16le":size*=2;o=__utf16le(this,this.l,this.l+size);break;default:switch(size){case 1:oI=__readUInt8(this,this.l);this.l++;return oI;case 2:oI=t!=="i"?__readUInt16LE(this,this.l):__readInt16LE(this,this.l);this.l+=2;return oI;case 4:if(t==="i"||(this[this.l+3]&128)===0){oI=__readInt32LE(this,this.l);this.l+=4;return oI}else{oR=__readUInt32LE(this,this.l);this.l+=4;return oR}break;case 8:if(t==="f"){oR=__double(this,this.l);this.l+=8;return oR}case 16:o=__hexlify(this,this.l,size);break}}this.l+=size;return o}function CheckField(hexstr,fld){var m=__hexlify(this,this.l,hexstr.length>>1);if(m!==hexstr)throw fld+"Expected "+hexstr+" saw "+m;this.l+=hexstr.length>>1}function prep_blob(blob,pos){blob.l=pos;blob.read_shift=ReadShift;blob.chk=CheckField}var SSF={};var make_ssf=function make_ssf(SSF){SSF.version="0.8.1";function _strrev(x){var o="",i=x.length-1;while(i>=0)o+=x.charAt(i--);return o}function fill(c,l){var o="";while(o.length<l)o+=c;return o}function pad0(v,d){var t=""+v;return t.length>=d?t:fill("0",d-t.length)+t}function pad_(v,d){var t=""+v;return t.length>=d?t:fill(" ",d-t.length)+t}function rpad_(v,d){var t=""+v;return t.length>=d?t:t+fill(" ",d-t.length)}function pad0r1(v,d){var t=""+Math.round(v);return t.length>=d?t:fill("0",d-t.length)+t}function pad0r2(v,d){var t=""+v;return t.length>=d?t:fill("0",d-t.length)+t}var p2_32=Math.pow(2,32);function pad0r(v,d){if(v>p2_32||v<-p2_32)return pad0r1(v,d);var i=Math.round(v);return pad0r2(i,d)}function isgeneral(s,i){return s.length>=7+i&&(s.charCodeAt(i)|32)===103&&(s.charCodeAt(i+1)|32)===101&&(s.charCodeAt(i+2)|32)===110&&(s.charCodeAt(i+3)|32)===101&&(s.charCodeAt(i+4)|32)===114&&(s.charCodeAt(i+5)|32)===97&&(s.charCodeAt(i+6)|32)===108}var opts_fmt=[["date1904",0],["output",""],["WTF",false]];function fixopts(o){for(var y=0;y!=opts_fmt.length;++y)if(o[opts_fmt[y][0]]===undefined)o[opts_fmt[y][0]]=opts_fmt[y][1]}SSF.opts=opts_fmt;var table_fmt={0:"General",1:"0",2:"0.00",3:"#,##0",4:"#,##0.00",9:"0%",10:"0.00%",11:"0.00E+00",12:"# ?/?",13:"# ??/??",14:"m/d/yy",15:"d-mmm-yy",16:"d-mmm",17:"mmm-yy",18:"h:mm AM/PM",19:"h:mm:ss AM/PM",20:"h:mm",21:"h:mm:ss",22:"m/d/yy h:mm",37:"#,##0 ;(#,##0)",38:"#,##0 ;[Red](#,##0)",39:"#,##0.00;(#,##0.00)",40:"#,##0.00;[Red](#,##0.00)",45:"mm:ss",46:"[h]:mm:ss",47:"mmss.0",48:"##0.0E+0",49:"@",56:'"上午/下午 "hh"時"mm"分"ss"秒 "',65535:"General"};var days=[["Sun","Sunday"],["Mon","Monday"],["Tue","Tuesday"],["Wed","Wednesday"],["Thu","Thursday"],["Fri","Friday"],["Sat","Saturday"]];var months=[["J","Jan","January"],["F","Feb","February"],["M","Mar","March"],["A","Apr","April"],["M","May","May"],["J","Jun","June"],["J","Jul","July"],["A","Aug","August"],["S","Sep","September"],["O","Oct","October"],["N","Nov","November"],["D","Dec","December"]];function frac(x,D,mixed){var sgn=x<0?-1:1;var B=x*sgn;var P_2=0,P_1=1,P=0;var Q_2=1,Q_1=0,Q=0;var A=Math.floor(B);while(Q_1<D){A=Math.floor(B);P=A*P_1+P_2;Q=A*Q_1+Q_2;if(B-A<5e-10)break;B=1/(B-A);P_2=P_1;P_1=P;Q_2=Q_1;Q_1=Q}if(Q>D){Q=Q_1;P=P_1}if(Q>D){Q=Q_2;P=P_2}if(!mixed)return[0,sgn*P,Q];if(Q===0)throw"Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;var q=Math.floor(sgn*P/Q);return[q,sgn*P-q*Q,Q]}function general_fmt_int(v,opts){return""+v}SSF._general_int=general_fmt_int;var general_fmt_num=function make_general_fmt_num(){var gnr1=/\.(\d*[1-9])0+$/,gnr2=/\.0*$/,gnr4=/\.(\d*[1-9])0+/,gnr5=/\.0*[Ee]/,gnr6=/(E[+-])(\d)$/;function gfn2(v){var w=v<0?12:11;var o=gfn5(v.toFixed(12));if(o.length<=w)return o;o=v.toPrecision(10);if(o.length<=w)return o;return v.toExponential(5)}function gfn3(v){var o=v.toFixed(11).replace(gnr1,".$1");if(o.length>(v<0?12:11))o=v.toPrecision(6);return o}function gfn4(o){for(var i=0;i!=o.length;++i)if((o.charCodeAt(i)|32)===101)return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");return o}function gfn5(o){return o.indexOf(".")>-1?o.replace(gnr2,"").replace(gnr1,".$1"):o}return function general_fmt_num(v,opts){var V=Math.floor(Math.log(Math.abs(v))*Math.LOG10E),o;if(V>=-4&&V<=-1)o=v.toPrecision(10+V);else if(Math.abs(V)<=9)o=gfn2(v);else if(V===10)o=v.toFixed(10).substr(0,12);else o=gfn3(v);return gfn5(gfn4(o))}}();SSF._general_num=general_fmt_num;function general_fmt(v,opts){switch(typeof v){case"string":return v;case"boolean":return v?"TRUE":"FALSE";case"number":return(v|0)===v?general_fmt_int(v,opts):general_fmt_num(v,opts)}throw new Error("unsupported value in General format: "+v)}SSF._general=general_fmt;function fix_hijri(date,o){return 0}function parse_date_code(v,opts,b2){if(v>2958465||v<0)return null;var date=v|0,time=Math.floor(86400*(v-date)),dow=0;var dout=[];var out={D:date,T:time,u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};if(Math.abs(out.u)<1e-6)out.u=0;fixopts(opts!=null?opts:opts=[]);if(opts.date1904)date+=1462;if(out.u>.999){out.u=0;if(++time==86400){time=0;++date}}if(date===60){dout=b2?[1317,10,29]:[1900,2,29];dow=3}else if(date===0){dout=b2?[1317,8,29]:[1900,1,0];dow=6}else{if(date>60)--date;var d=new Date(1900,0,1);d.setDate(d.getDate()+date-1);dout=[d.getFullYear(),d.getMonth()+1,d.getDate()];dow=d.getDay();if(date<60)dow=(dow+6)%7;if(b2)dow=fix_hijri(d,dout)}out.y=dout[0];out.m=dout[1];out.d=dout[2];out.S=time%60;time=Math.floor(time/60);out.M=time%60;time=Math.floor(time/60);out.H=time;out.q=dow;return out}SSF.parse_date_code=parse_date_code;function write_date(type,fmt,val,ss0){var o="",ss=0,tt=0,y=val.y,out,outl=0;switch(type){case 98:y=val.y+543;case 121:switch(fmt.length){case 1:case 2:out=y%100;outl=2;break;default:out=y%1e4;outl=4;break}break;case 109:switch(fmt.length){case 1:case 2:out=val.m;outl=fmt.length;break;case 3:return months[val.m-1][1];case 5:return months[val.m-1][0];default:return months[val.m-1][2]}break;case 100:switch(fmt.length){case 1:case 2:out=val.d;outl=fmt.length;break;case 3:return days[val.q][0];default:return days[val.q][1]}break;case 104:switch(fmt.length){case 1:case 2:out=1+(val.H+11)%12;outl=fmt.length;break;default:throw"bad hour format: "+fmt}break;case 72:switch(fmt.length){case 1:case 2:out=val.H;outl=fmt.length;break;default:throw"bad hour format: "+fmt}break;case 77:switch(fmt.length){case 1:case 2:out=val.M;outl=fmt.length;break;default:throw"bad minute format: "+fmt}break;case 115:if(val.u===0)switch(fmt){case"s":case"ss":return pad0(val.S,fmt.length);case".0":case".00":case".000":}switch(fmt){case"s":case"ss":case".0":case".00":case".000":if(ss0>=2)tt=ss0===3?1e3:100;else tt=ss0===1?10:1;ss=Math.round(tt*(val.S+val.u));if(ss>=60*tt)ss=0;if(fmt==="s")return ss===0?"0":""+ss/tt;o=pad0(ss,2+ss0);if(fmt==="ss")return o.substr(0,2);return"."+o.substr(2,fmt.length-1);default:throw"bad second format: "+fmt}case 90:switch(fmt){case"[h]":case"[hh]":out=val.D*24+val.H;break;case"[m]":case"[mm]":out=(val.D*24+val.H)*60+val.M;break;case"[s]":case"[ss]":out=((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u);break;default:throw"bad abstime format: "+fmt}outl=fmt.length===3?1:2;break;case 101:out=y;outl=1}if(outl>0)return pad0(out,outl);else return""}function commaify(s){if(s.length<=3)return s;var j=s.length%3,o=s.substr(0,j);for(;j!=s.length;j+=3)o+=(o.length>0?",":"")+s.substr(j,3);return o}var write_num=function make_write_num(){var pct1=/%/g;function write_num_pct(type,fmt,val){var sfmt=fmt.replace(pct1,""),mul=fmt.length-sfmt.length;return write_num(type,sfmt,val*Math.pow(10,2*mul))+fill("%",mul)}function write_num_cm(type,fmt,val){var idx=fmt.length-1;while(fmt.charCodeAt(idx-1)===44)--idx;return write_num(type,fmt.substr(0,idx),val/Math.pow(10,3*(fmt.length-idx)))}function write_num_exp(fmt,val){var o;var idx=fmt.indexOf("E")-fmt.indexOf(".")-1;if(fmt.match(/^#+0.0E\+0$/)){var period=fmt.indexOf(".");if(period===-1)period=fmt.indexOf("E");var ee=Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;if(ee<0)ee+=period;o=(val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);if(o.indexOf("e")===-1){var fakee=Math.floor(Math.log(Math.abs(val))*Math.LOG10E);if(o.indexOf(".")===-1)o=o[0]+"."+o.substr(1)+"E+"+(fakee-o.length+ee);else o+="E+"+(fakee-ee);while(o.substr(0,2)==="0."){o=o[0]+o.substr(2,period)+"."+o.substr(2+period);o=o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.")}o=o.replace(/\+-/,"-")}o=o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3){return $1+$2+$3.substr(0,(period+ee)%period)+"."+$3.substr(ee)+"E"})}else o=val.toExponential(idx);if(fmt.match(/E\+00$/)&&o.match(/e[+-]\d$/))o=o.substr(0,o.length-1)+"0"+o[o.length-1];if(fmt.match(/E\-/)&&o.match(/e\+/))o=o.replace(/e\+/,"e");return o.replace("e","E")}var frac1=/# (\?+)( ?)\/( ?)(\d+)/;function write_num_f1(r,aval,sign){var den=parseInt(r[4]),rr=Math.round(aval*den),base=Math.floor(rr/den);var myn=rr-base*den,myd=den;return sign+(base===0?"":""+base)+" "+(myn===0?fill(" ",r[1].length+1+r[4].length):pad_(myn,r[1].length)+r[2]+"/"+r[3]+pad0(myd,r[4].length))}function write_num_f2(r,aval,sign){return sign+(aval===0?"":""+aval)+fill(" ",r[1].length+2+r[4].length)}var dec1=/^#*0*\.(0+)/;var closeparen=/\).*[0#]/;var phone=/\(###\) ###\\?-####/;function hashq(str){var o="",cc;for(var i=0;i!=str.length;++i)switch(cc=str.charCodeAt(i)){case 35:break;case 63:o+=" ";break;case 48:o+="0";break;default:o+=String.fromCharCode(cc)}return o}function rnd(val,d){var dd=Math.pow(10,d);return""+Math.round(val*dd)/dd}function dec(val,d){return Math.round((val-Math.floor(val))*Math.pow(10,d))}function flr(val){if(val<2147483647&&val>-2147483648)return""+(val>=0?val|0:val-1|0);return""+Math.floor(val)}function write_num_flt(type,fmt,val){if(type.charCodeAt(0)===40&&!fmt.match(closeparen)){var ffmt=fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");if(val>=0)return write_num_flt("n",ffmt,val);return"("+write_num_flt("n",ffmt,-val)+")"}if(fmt.charCodeAt(fmt.length-1)===44)return write_num_cm(type,fmt,val);if(fmt.indexOf("%")!==-1)return write_num_pct(type,fmt,val);if(fmt.indexOf("E")!==-1)return write_num_exp(fmt,val);if(fmt.charCodeAt(0)===36)return"$"+write_num_flt(type,fmt.substr(fmt[1]==" "?2:1),val);var o,oo;var r,ri,ff,aval=Math.abs(val),sign=val<0?"-":"";if(fmt.match(/^00+$/))return sign+pad0r(aval,fmt.length);if(fmt.match(/^[#?]+$/)){o=pad0r(val,0);if(o==="0")o="";return o.length>fmt.length?o:hashq(fmt.substr(0,fmt.length-o.length))+o}if((r=fmt.match(frac1))!==null)return write_num_f1(r,aval,sign);if(fmt.match(/^#+0+$/)!==null)return sign+pad0r(aval,fmt.length-fmt.indexOf("0"));if((r=fmt.match(dec1))!==null){o=rnd(val,r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$,$1){return"."+$1+fill("0",r[1].length-$1.length)});return fmt.indexOf("0.")!==-1?o:o.replace(/^0\./,".")}fmt=fmt.replace(/^#+([0.])/,"$1");if((r=fmt.match(/^(0*)\.(#*)$/))!==null){return sign+rnd(aval,r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".")}if((r=fmt.match(/^#,##0(\.?)$/))!==null)return sign+commaify(pad0r(aval,0));if((r=fmt.match(/^#,##0\.([#0]*0)$/))!==null){return val<0?"-"+write_num_flt(type,fmt,-val):commaify(""+Math.floor(val))+"."+pad0(dec(val,r[1].length),r[1].length)}if((r=fmt.match(/^#,#*,#0/))!==null)return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);if((r=fmt.match(/^([0#]+)(\\?-([0#]+))+$/))!==null){o=_strrev(write_num_flt(type,fmt.replace(/[\\-]/g,""),val));ri=0;return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==="0"?"0":""}))}if(fmt.match(phone)!==null){o=write_num_flt(type,"##########",val);return"("+o.substr(0,3)+") "+o.substr(3,3)+"-"+o.substr(6)}var oa="";if((r=fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))!==null){ri=Math.min(r[4].length,7);ff=frac(aval,Math.pow(10,ri)-1,false);o=""+sign;oa=write_num("n",r[1],ff[1]);if(oa[oa.length-1]==" ")oa=oa.substr(0,oa.length-1)+"0";o+=oa+r[2]+"/"+r[3];oa=rpad_(ff[2],ri);if(oa.length<r[4].length)oa=hashq(r[4].substr(r[4].length-oa.length))+oa;o+=oa;return o}if((r=fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))!==null){ri=Math.min(Math.max(r[1].length,r[4].length),7);ff=frac(aval,Math.pow(10,ri)-1,true);return sign+(ff[0]||(ff[1]?"":"0"))+" "+(ff[1]?pad_(ff[1],ri)+r[2]+"/"+r[3]+rpad_(ff[2],ri):fill(" ",2*ri+1+r[2].length+r[3].length))}if((r=fmt.match(/^[#0?]+$/))!==null){o=pad0r(val,0);if(fmt.length<=o.length)return o;return hashq(fmt.substr(0,fmt.length-o.length))+o}if((r=fmt.match(/^([#0?]+)\.([#0]+)$/))!==null){o=""+val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");ri=o.indexOf(".");var lres=fmt.indexOf(".")-ri,rres=fmt.length-o.length-lres;return hashq(fmt.substr(0,lres)+o+fmt.substr(fmt.length-rres))}if((r=fmt.match(/^00,000\.([#0]*0)$/))!==null){ri=dec(val,r[1].length);return val<0?"-"+write_num_flt(type,fmt,-val):commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$){return"00,"+($$.length<3?pad0(0,3-$$.length):"")+$$})+"."+pad0(ri,r[1].length)}switch(fmt){case"#,###":var x=commaify(pad0r(aval,0));return x!=="0"?sign+x:"";default:}throw new Error("unsupported format |"+fmt+"|")}function write_num_cm2(type,fmt,val){var idx=fmt.length-1;while(fmt.charCodeAt(idx-1)===44)--idx;return write_num(type,fmt.substr(0,idx),val/Math.pow(10,3*(fmt.length-idx)))}function write_num_pct2(type,fmt,val){var sfmt=fmt.replace(pct1,""),mul=fmt.length-sfmt.length;return write_num(type,sfmt,val*Math.pow(10,2*mul))+fill("%",mul)}function write_num_exp2(fmt,val){var o;var idx=fmt.indexOf("E")-fmt.indexOf(".")-1;if(fmt.match(/^#+0.0E\+0$/)){var period=fmt.indexOf(".");if(period===-1)period=fmt.indexOf("E");var ee=Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;if(ee<0)ee+=period;o=(val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);if(!o.match(/[Ee]/)){var fakee=Math.floor(Math.log(Math.abs(val))*Math.LOG10E);if(o.indexOf(".")===-1)o=o[0]+"."+o.substr(1)+"E+"+(fakee-o.length+ee);else o+="E+"+(fakee-ee);o=o.replace(/\+-/,"-")}o=o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3){return $1+$2+$3.substr(0,(period+ee)%period)+"."+$3.substr(ee)+"E"})}else o=val.toExponential(idx);if(fmt.match(/E\+00$/)&&o.match(/e[+-]\d$/))o=o.substr(0,o.length-1)+"0"+o[o.length-1];if(fmt.match(/E\-/)&&o.match(/e\+/))o=o.replace(/e\+/,"e");return o.replace("e","E")}function write_num_int(type,fmt,val){if(type.charCodeAt(0)===40&&!fmt.match(closeparen)){var ffmt=fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");if(val>=0)return write_num_int("n",ffmt,val);return"("+write_num_int("n",ffmt,-val)+")"}if(fmt.charCodeAt(fmt.length-1)===44)return write_num_cm2(type,fmt,val);if(fmt.indexOf("%")!==-1)return write_num_pct2(type,fmt,val);if(fmt.indexOf("E")!==-1)return write_num_exp2(fmt,val);if(fmt.charCodeAt(0)===36)return"$"+write_num_int(type,fmt.substr(fmt[1]==" "?2:1),val);var o;var r,ri,ff,aval=Math.abs(val),sign=val<0?"-":"";if(fmt.match(/^00+$/))return sign+pad0(aval,fmt.length);if(fmt.match(/^[#?]+$/)){o=""+val;if(val===0)o="";return o.length>fmt.length?o:hashq(fmt.substr(0,fmt.length-o.length))+o}if((r=fmt.match(frac1))!==null)return write_num_f2(r,aval,sign);if(fmt.match(/^#+0+$/)!==null)return sign+pad0(aval,fmt.length-fmt.indexOf("0"));if((r=fmt.match(dec1))!==null){o=(""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$,$1){return"."+$1+fill("0",r[1].length-$1.length)});return fmt.indexOf("0.")!==-1?o:o.replace(/^0\./,".")}fmt=fmt.replace(/^#+([0.])/,"$1");if((r=fmt.match(/^(0*)\.(#*)$/))!==null){return sign+(""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".")}if((r=fmt.match(/^#,##0(\.?)$/))!==null)return sign+commaify(""+aval);if((r=fmt.match(/^#,##0\.([#0]*0)$/))!==null){return val<0?"-"+write_num_int(type,fmt,-val):commaify(""+val)+"."+fill("0",r[1].length)}if((r=fmt.match(/^#,#*,#0/))!==null)return write_num_int(type,fmt.replace(/^#,#*,/,""),val);if((r=fmt.match(/^([0#]+)(\\?-([0#]+))+$/))!==null){o=_strrev(write_num_int(type,fmt.replace(/[\\-]/g,""),val));ri=0;return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==="0"?"0":""}))}if(fmt.match(phone)!==null){o=write_num_int(type,"##########",val);return"("+o.substr(0,3)+") "+o.substr(3,3)+"-"+o.substr(6)}var oa="";if((r=fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))!==null){ri=Math.min(r[4].length,7);ff=frac(aval,Math.pow(10,ri)-1,false);o=""+sign;oa=write_num("n",r[1],ff[1]);if(oa[oa.length-1]==" ")oa=oa.substr(0,oa.length-1)+"0";o+=oa+r[2]+"/"+r[3];oa=rpad_(ff[2],ri);if(oa.length<r[4].length)oa=hashq(r[4].substr(r[4].length-oa.length))+oa;o+=oa;return o}if((r=fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))!==null){ri=Math.min(Math.max(r[1].length,r[4].length),7);ff=frac(aval,Math.pow(10,ri)-1,true);return sign+(ff[0]||(ff[1]?"":"0"))+" "+(ff[1]?pad_(ff[1],ri)+r[2]+"/"+r[3]+rpad_(ff[2],ri):fill(" ",2*ri+1+r[2].length+r[3].length))}if((r=fmt.match(/^[#0?]+$/))!==null){o=""+val;if(fmt.length<=o.length)return o;return hashq(fmt.substr(0,fmt.length-o.length))+o}if((r=fmt.match(/^([#0]+)\.([#0]+)$/))!==null){o=""+val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");ri=o.indexOf(".");var lres=fmt.indexOf(".")-ri,rres=fmt.length-o.length-lres;return hashq(fmt.substr(0,lres)+o+fmt.substr(fmt.length-rres))}if((r=fmt.match(/^00,000\.([#0]*0)$/))!==null){return val<0?"-"+write_num_int(type,fmt,-val):commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$){return"00,"+($$.length<3?pad0(0,3-$$.length):"")+$$})+"."+pad0(0,r[1].length)}switch(fmt){case"#,###":var x=commaify(""+aval);return x!=="0"?sign+x:"";default:}throw new Error("unsupported format |"+fmt+"|")}return function write_num(type,fmt,val){return(val|0)===val?write_num_int(type,fmt,val):write_num_flt(type,fmt,val)}}();function split_fmt(fmt){var out=[];var in_str=false,cc;for(var i=0,j=0;i<fmt.length;++i)switch(cc=fmt.charCodeAt(i)){case 34:in_str=!in_str;break;case 95:case 42:case 92:++i;break;case 59:out[out.length]=fmt.substr(j,i-j);j=i+1}out[out.length]=fmt.substr(j);if(in_str===true)throw new Error("Format |"+fmt+"| unterminated string ");return out}SSF._split=split_fmt;var abstime=/\[[HhMmSs]*\]/;function eval_fmt(fmt,v,opts,flen){var out=[],o="",i=0,c="",lst="t",q,dt,j,cc;var hr="H";while(i<fmt.length){switch(c=fmt[i]){case"G":if(!isgeneral(fmt,i))throw new Error("unrecognized character "+c+" in "+fmt);out[out.length]={t:"G",v:"General"};i+=7;break;case'"':for(o="";(cc=fmt.charCodeAt(++i))!==34&&i<fmt.length;)o+=String.fromCharCode(cc);out[out.length]={t:"t",v:o};++i;break;case"\\":var w=fmt[++i],t=w==="("||w===")"?w:"t";out[out.length]={t:t,v:w};++i;break;case"_":out[out.length]={t:"t",v:" "};i+=2;break;case"@":out[out.length]={t:"T",v:v};++i;break;case"B":case"b":if(fmt[i+1]==="1"||fmt[i+1]==="2"){if(dt==null){dt=parse_date_code(v,opts,fmt[i+1]==="2");if(dt==null)return""}out[out.length]={t:"X",v:fmt.substr(i,2)};lst=c;i+=2;break}case"M":case"D":case"Y":case"H":case"S":case"E":c=c.toLowerCase();case"m":case"d":case"y":case"h":case"s":case"e":case"g":if(v<0)return"";if(dt==null){dt=parse_date_code(v,opts);if(dt==null)return""}o=c;while(++i<fmt.length&&fmt[i].toLowerCase()===c)o+=c;if(c==="m"&&lst.toLowerCase()==="h")c="M";if(c==="h")c=hr;out[out.length]={t:c,v:o};lst=c;break;case"A":q={t:c,v:"A"};if(dt==null)dt=parse_date_code(v,opts);if(fmt.substr(i,3)==="A/P"){if(dt!=null)q.v=dt.H>=12?"P":"A";q.t="T";hr="h";i+=3}else if(fmt.substr(i,5)==="AM/PM"){if(dt!=null)q.v=dt.H>=12?"PM":"AM";q.t="T";i+=5;hr="h"}else{q.t="t";++i}if(dt==null&&q.t==="T")return"";out[out.length]=q;lst=c;break;case"[":o=c;while(fmt[i++]!=="]"&&i<fmt.length)o+=fmt[i];if(o.substr(-1)!=="]")throw'unterminated "[" block: |'+o+"|";if(o.match(abstime)){if(dt==null){dt=parse_date_code(v,opts);if(dt==null)return""}out[out.length]={t:"Z",v:o.toLowerCase()}}else{o=""}break;case".":if(dt!=null){o=c;while((c=fmt[++i])==="0")o+=c;out[out.length]={t:"s",v:o};break}case"0":case"#":o=c;while("0#?.,E+-%".indexOf(c=fmt[++i])>-1||c=="\\"&&fmt[i+1]=="-"&&"0#".indexOf(fmt[i+2])>-1)o+=c;out[out.length]={t:"n",v:o};break;case"?":o=c;while(fmt[++i]===c)o+=c;q={t:c,v:o};out[out.length]=q;lst=c;break;case"*":++i;if(fmt[i]==" "||fmt[i]=="*")++i;break;case"(":case")":out[out.length]={t:flen===1?"t":c,v:c};++i;break;case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":o=c;while("0123456789".indexOf(fmt[++i])>-1)o+=fmt[i];out[out.length]={t:"D",v:o};break;case" ":out[out.length]={t:c,v:c};++i;break;default:if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxz".indexOf(c)===-1)throw new Error("unrecognized character "+c+" in "+fmt);out[out.length]={t:"t",v:c};++i;break}}var bt=0,ss0=0,ssm;for(i=out.length-1,lst="t";i>=0;--i){switch(out[i].t){case"h":case"H":out[i].t=hr;lst="h";if(bt<1)bt=1;break;case"s":if(ssm=out[i].v.match(/\.0+$/))ss0=Math.max(ss0,ssm[0].length-1);if(bt<3)bt=3;case"d":case"y":case"M":case"e":lst=out[i].t;break;case"m":if(lst==="s"){out[i].t="M";if(bt<2)bt=2}break;case"X":if(out[i].v==="B2");break;case"Z":if(bt<1&&out[i].v.match(/[Hh]/))bt=1;if(bt<2&&out[i].v.match(/[Mm]/))bt=2;if(bt<3&&out[i].v.match(/[Ss]/))bt=3}}switch(bt){case 0:break;case 1:if(dt.u>=.5){dt.u=0;++dt.S}if(dt.S>=60){dt.S=0;++dt.M}if(dt.M>=60){dt.M=0;++dt.H}break;case 2:if(dt.u>=.5){dt.u=0;++dt.S}if(dt.S>=60){dt.S=0;++dt.M}break}var nstr="",jj;for(i=0;i<out.length;++i){switch(out[i].t){case"t":case"T":case" ":case"D":break;case"X":out[i]=undefined;break;case"d":case"m":case"y":case"h":case"H":case"M":case"s":case"e":case"b":case"Z":out[i].v=write_date(out[i].t.charCodeAt(0),out[i].v,dt,ss0);out[i].t="t";break;case"n":case"(":case"?":jj=i+1;while(out[jj]!=null&&((c=out[jj].t)==="?"||c==="D"||(c===" "||c==="t")&&out[jj+1]!=null&&(out[jj+1].t==="?"||out[jj+1].t==="t"&&out[jj+1].v==="/")||out[i].t==="("&&(c===" "||c==="n"||c===")")||c==="t"&&(out[jj].v==="/"||"$€".indexOf(out[jj].v)>-1||out[jj].v===" "&&out[jj+1]!=null&&out[jj+1].t=="?"))){out[i].v+=out[jj].v;out[jj]=undefined;++jj}nstr+=out[i].v;i=jj-1;break;case"G":out[i].t="t";out[i].v=general_fmt(v,opts);break}}var vv="",myv,ostr;if(nstr.length>0){myv=v<0&&nstr.charCodeAt(0)===45?-v:v;ostr=write_num(nstr.charCodeAt(0)===40?"(":"n",nstr,myv);jj=ostr.length-1;var decpt=out.length;for(i=0;i<out.length;++i)if(out[i]!=null&&out[i].v.indexOf(".")>-1){decpt=i;break}var lasti=out.length;if(decpt===out.length&&ostr.indexOf("E")===-1){for(i=out.length-1;i>=0;--i){if(out[i]==null||"n?(".indexOf(out[i].t)===-1)continue;if(jj>=out[i].v.length-1){jj-=out[i].v.length;out[i].v=ostr.substr(jj+1,out[i].v.length)}else if(jj<0)out[i].v="";else{out[i].v=ostr.substr(0,jj+1);jj=-1}out[i].t="t";lasti=i}if(jj>=0&&lasti<out.length)out[lasti].v=ostr.substr(0,jj+1)+out[lasti].v}else if(decpt!==out.length&&ostr.indexOf("E")===-1){jj=ostr.indexOf(".")-1;for(i=decpt;i>=0;--i){if(out[i]==null||"n?(".indexOf(out[i].t)===-1)continue;j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;vv=out[i].v.substr(j+1);for(;j>=0;--j){if(jj>=0&&(out[i].v[j]==="0"||out[i].v[j]==="#"))vv=ostr[jj--]+vv}out[i].v=vv;out[i].t="t";lasti=i}if(jj>=0&&lasti<out.length)out[lasti].v=ostr.substr(0,jj+1)+out[lasti].v;jj=ostr.indexOf(".")+1;for(i=decpt;i<out.length;++i){if(out[i]==null||"n?(".indexOf(out[i].t)===-1&&i!==decpt)continue;j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;vv=out[i].v.substr(0,j);for(;j<out[i].v.length;++j){if(jj<ostr.length)vv+=ostr[jj++]}out[i].v=vv;out[i].t="t";lasti=i}}}for(i=0;i<out.length;++i)if(out[i]!=null&&"n(?".indexOf(out[i].t)>-1){myv=flen>1&&v<0&&i>0&&out[i-1].v==="-"?-v:v;out[i].v=write_num(out[i].t,out[i].v,myv);out[i].t="t"}var retval="";for(i=0;i!==out.length;++i)if(out[i]!=null)retval+=out[i].v;return retval}SSF._eval=eval_fmt;var cfregex=/\[[=<>]/;var cfregex2=/\[([=<>]*)(-?\d+\.?\d*)\]/;function chkcond(v,rr){if(rr==null)return false;var thresh=parseFloat(rr[2]);switch(rr[1]){case"=":if(v==thresh)return true;break;case">":if(v>thresh)return true;break;case"<":if(v<thresh)return true;break;case"<>":if(v!=thresh)return true;break;case">=":if(v>=thresh)return true;break;case"<=":if(v<=thresh)return true;break}return false}function choose_fmt(f,v){var fmt=split_fmt(f);var l=fmt.length,lat=fmt[l-1].indexOf("@");if(l<4&&lat>-1)--l;if(fmt.length>4)throw"cannot find right format for |"+fmt+"|";if(typeof v!=="number")return[4,fmt.length===4||lat>-1?fmt[fmt.length-1]:"@"];switch(fmt.length){case 1:fmt=lat>-1?["General","General","General",fmt[0]]:[fmt[0],fmt[0],fmt[0],"@"];break;case 2:fmt=lat>-1?[fmt[0],fmt[0],fmt[0],fmt[1]]:[fmt[0],fmt[1],fmt[0],"@"];break;case 3:fmt=lat>-1?[fmt[0],fmt[1],fmt[0],fmt[2]]:[fmt[0],fmt[1],fmt[2],"@"];break;case 4:break}var ff=v>0?fmt[0]:v<0?fmt[1]:fmt[2];if(fmt[0].indexOf("[")===-1&&fmt[1].indexOf("[")===-1)return[l,ff];if(fmt[0].match(cfregex)!=null||fmt[1].match(cfregex)!=null){var m1=fmt[0].match(cfregex2);var m2=fmt[1].match(cfregex2);return chkcond(v,m1)?[l,fmt[0]]:chkcond(v,m2)?[l,fmt[1]]:[l,fmt[m1!=null&&m2!=null?2:1]]}return[l,ff]}function format(fmt,v,o){fixopts(o!=null?o:o=[]);var sfmt="";switch(typeof fmt){case"string":sfmt=fmt;break;case"number":sfmt=(o.table!=null?o.table:table_fmt)[fmt];break}if(isgeneral(sfmt,0))return general_fmt(v,o);var f=choose_fmt(sfmt,v);if(isgeneral(f[1]))return general_fmt(v,o);if(v===true)v="TRUE";else if(v===false)v="FALSE";else if(v===""||v==null)return"";return eval_fmt(f[1],v,o,f[0])}SSF._table=table_fmt;SSF.load=function load_entry(fmt,idx){table_fmt[idx]=fmt};SSF.format=format;SSF.get_table=function get_table(){return table_fmt};SSF.load_table=function load_table(tbl){for(var i=0;i!=392;++i)if(tbl[i]!==undefined)SSF.load(tbl[i],i)}};make_ssf(SSF);{var VT_EMPTY=0;var VT_NULL=1;var VT_I2=2;var VT_I4=3;var VT_R4=4;var VT_R8=5;var VT_CY=6;var VT_DATE=7;var VT_BSTR=8;var VT_ERROR=10;var VT_BOOL=11;var VT_VARIANT=12;var VT_DECIMAL=14;var VT_I1=16;var VT_UI1=17;var VT_UI2=18;var VT_UI4=19;var VT_I8=20;var VT_UI8=21;var VT_INT=22;var VT_UINT=23;var VT_LPSTR=30;var VT_LPWSTR=31;var VT_FILETIME=64;var VT_BLOB=65;var VT_STREAM=66;var VT_STORAGE=67;var VT_STREAMED_Object=68;
18559 var VT_STORED_Object=69;var VT_BLOB_Object=70;var VT_CF=71;var VT_CLSID=72;var VT_VERSIONED_STREAM=73;var VT_VECTOR=4096;var VT_ARRAY=8192;var VT_STRING=80;var VT_USTR=81;var VT_CUSTOM=[VT_STRING,VT_USTR]}var DocSummaryPIDDSI={1:{n:"CodePage",t:VT_I2},2:{n:"Category",t:VT_STRING},3:{n:"PresentationFormat",t:VT_STRING},4:{n:"ByteCount",t:VT_I4},5:{n:"LineCount",t:VT_I4},6:{n:"ParagraphCount",t:VT_I4},7:{n:"SlideCount",t:VT_I4},8:{n:"NoteCount",t:VT_I4},9:{n:"HiddenCount",t:VT_I4},10:{n:"MultimediaClipCount",t:VT_I4},11:{n:"Scale",t:VT_BOOL},12:{n:"HeadingPair",t:VT_VECTOR|VT_VARIANT},13:{n:"DocParts",t:VT_VECTOR|VT_LPSTR},14:{n:"Manager",t:VT_STRING},15:{n:"Company",t:VT_STRING},16:{n:"LinksDirty",t:VT_BOOL},17:{n:"CharacterCount",t:VT_I4},19:{n:"SharedDoc",t:VT_BOOL},22:{n:"HLinksChanged",t:VT_BOOL},23:{n:"AppVersion",t:VT_I4,p:"version"},26:{n:"ContentType",t:VT_STRING},27:{n:"ContentStatus",t:VT_STRING},28:{n:"Language",t:VT_STRING},29:{n:"Version",t:VT_STRING},255:{}};var SummaryPIDSI={1:{n:"CodePage",t:VT_I2},2:{n:"Title",t:VT_STRING},3:{n:"Subject",t:VT_STRING},4:{n:"Author",t:VT_STRING},5:{n:"Keywords",t:VT_STRING},6:{n:"Comments",t:VT_STRING},7:{n:"Template",t:VT_STRING},8:{n:"LastAuthor",t:VT_STRING},9:{n:"RevNumber",t:VT_STRING},10:{n:"EditTime",t:VT_FILETIME},11:{n:"LastPrinted",t:VT_FILETIME},12:{n:"CreatedDate",t:VT_FILETIME},13:{n:"ModifiedDate",t:VT_FILETIME},14:{n:"PageCount",t:VT_I4},15:{n:"WordCount",t:VT_I4},16:{n:"CharCount",t:VT_I4},17:{n:"Thumbnail",t:VT_CF},18:{n:"ApplicationName",t:VT_LPSTR},19:{n:"DocumentSecurity",t:VT_I4},255:{}};var SpecialProperties={2147483648:{n:"Locale",t:VT_UI4},2147483651:{n:"Behavior",t:VT_UI4},1768515945:{}};(function(){for(var y in SpecialProperties)if(SpecialProperties.hasOwnProperty(y))DocSummaryPIDDSI[y]=SummaryPIDSI[y]=SpecialProperties[y]})();function parse_FILETIME(blob){var dwLowDateTime=blob.read_shift(4),dwHighDateTime=blob.read_shift(4);return new Date((dwHighDateTime/1e7*Math.pow(2,32)+dwLowDateTime/1e7-11644473600)*1e3).toISOString().replace(/\.000/,"")}function parse_lpstr(blob,type,pad){var str=blob.read_shift(0,"lpstr");if(pad)blob.l+=4-(str.length+1&3)&3;return str}function parse_lpwstr(blob,type,pad){var str=blob.read_shift(0,"lpwstr");if(pad)blob.l+=4-(str.length+1&3)&3;return str}function parse_VtStringBase(blob,stringType,pad){if(stringType===31)return parse_lpwstr(blob);return parse_lpstr(blob,stringType,pad)}function parse_VtString(blob,t,pad){return parse_VtStringBase(blob,t,pad===false?0:4)}function parse_VtUnalignedString(blob,t){if(!t)throw new Error("dafuq?");return parse_VtStringBase(blob,t,0)}function parse_VtVecUnalignedLpstrValue(blob){var length=blob.read_shift(4);var ret=[];for(var i=0;i!=length;++i)ret[i]=blob.read_shift(0,"lpstr");return ret}function parse_VtVecUnalignedLpstr(blob){return parse_VtVecUnalignedLpstrValue(blob)}function parse_VtHeadingPair(blob){var headingString=parse_TypedPropertyValue(blob,VT_USTR);var headerParts=parse_TypedPropertyValue(blob,VT_I4);return[headingString,headerParts]}function parse_VtVecHeadingPairValue(blob){var cElements=blob.read_shift(4);var out=[];for(var i=0;i!=cElements/2;++i)out.push(parse_VtHeadingPair(blob));return out}function parse_VtVecHeadingPair(blob){return parse_VtVecHeadingPairValue(blob)}function parse_dictionary(blob,CodePage){var cnt=blob.read_shift(4);var dict={};for(var j=0;j!=cnt;++j){var pid=blob.read_shift(4);var len=blob.read_shift(4);dict[pid]=blob.read_shift(len,CodePage===1200?"utf16le":"utf8").replace(chr0,"").replace(chr1,"!")}if(blob.l&3)blob.l=blob.l>>2+1<<2;return dict}function parse_BLOB(blob){var size=blob.read_shift(4);var bytes=blob.slice(blob.l,blob.l+size);if(size&3>0)blob.l+=4-(size&3)&3;return bytes}function parse_ClipboardData(blob){var o={};o.Size=blob.read_shift(4);blob.l+=o.Size;return o}function parse_VtVector(blob,cb){}function parse_TypedPropertyValue(blob,type,_opts){var t=blob.read_shift(2),ret,opts=_opts||{};blob.l+=2;if(type!==VT_VARIANT)if(t!==type&&VT_CUSTOM.indexOf(type)===-1)throw new Error("Expected type "+type+" saw "+t);switch(type===VT_VARIANT?t:type){case 2:ret=blob.read_shift(2,"i");if(!opts.raw)blob.l+=2;return ret;case 3:ret=blob.read_shift(4,"i");return ret;case 11:return blob.read_shift(4)!==0;case 19:ret=blob.read_shift(4);return ret;case 30:return parse_lpstr(blob,t,4).replace(chr0,"");case 31:return parse_lpwstr(blob);case 64:return parse_FILETIME(blob);case 65:return parse_BLOB(blob);case 71:return parse_ClipboardData(blob);case 80:return parse_VtString(blob,t,!opts.raw&&4).replace(chr0,"");case 81:return parse_VtUnalignedString(blob,t,4).replace(chr0,"");case 4108:return parse_VtVecHeadingPair(blob);case 4126:return parse_VtVecUnalignedLpstr(blob);default:throw new Error("TypedPropertyValue unrecognized type "+type+" "+t)}}function parse_PropertySet(blob,PIDSI){var start_addr=blob.l;var size=blob.read_shift(4);var NumProps=blob.read_shift(4);var Props=[],i=0;var CodePage=0;var Dictionary=-1,DictObj;for(i=0;i!=NumProps;++i){var PropID=blob.read_shift(4);var Offset=blob.read_shift(4);Props[i]=[PropID,Offset+start_addr]}var PropH={};for(i=0;i!=NumProps;++i){if(blob.l!==Props[i][1]){var fail=true;if(i>0&&PIDSI)switch(PIDSI[Props[i-1][0]].t){case 2:if(blob.l+2===Props[i][1]){blob.l+=2;fail=false}break;case 80:if(blob.l<=Props[i][1]){blob.l=Props[i][1];fail=false}break;case 4108:if(blob.l<=Props[i][1]){blob.l=Props[i][1];fail=false}break}if(!PIDSI&&blob.l<=Props[i][1]){fail=false;blob.l=Props[i][1]}if(fail)throw new Error("Read Error: Expected address "+Props[i][1]+" at "+blob.l+" :"+i)}if(PIDSI){var piddsi=PIDSI[Props[i][0]];PropH[piddsi.n]=parse_TypedPropertyValue(blob,piddsi.t,{raw:true});if(piddsi.p==="version")PropH[piddsi.n]=String(PropH[piddsi.n]>>16)+"."+String(PropH[piddsi.n]&65535);if(piddsi.n=="CodePage")switch(PropH[piddsi.n]){case 0:PropH[piddsi.n]=1252;case 1e4:case 1252:case 874:case 1250:case 1251:case 1253:case 1254:case 1255:case 1256:case 1257:case 1258:case 932:case 936:case 949:case 950:case 1200:case 1201:case 65e3:case-536:case 65001:case-535:set_cp(CodePage=PropH[piddsi.n]);break;default:throw new Error("Unsupported CodePage: "+PropH[piddsi.n])}}else{if(Props[i][0]===1){CodePage=PropH.CodePage=parse_TypedPropertyValue(blob,VT_I2);set_cp(CodePage);if(Dictionary!==-1){var oldpos=blob.l;blob.l=Props[Dictionary][1];DictObj=parse_dictionary(blob,CodePage);blob.l=oldpos}}else if(Props[i][0]===0){if(CodePage===0){Dictionary=i;blob.l=Props[i+1][1];continue}DictObj=parse_dictionary(blob,CodePage)}else{var name=DictObj[Props[i][0]];var val;switch(blob[blob.l]){case 65:blob.l+=4;val=parse_BLOB(blob);break;case 30:blob.l+=4;val=parse_VtString(blob,blob[blob.l-4]);break;case 31:blob.l+=4;val=parse_VtString(blob,blob[blob.l-4]);break;case 3:blob.l+=4;val=blob.read_shift(4,"i");break;case 19:blob.l+=4;val=blob.read_shift(4);break;case 5:blob.l+=4;val=blob.read_shift(8,"f");break;case 11:blob.l+=4;val=parsebool(blob,4);break;case 64:blob.l+=4;val=new Date(parse_FILETIME(blob));break;default:throw new Error("unparsed value: "+blob[blob.l])}PropH[name]=val}}}blob.l=start_addr+size;return PropH}function parse_PropertySetStream(file,PIDSI){var blob=file.content;prep_blob(blob,0);var NumSets,FMTID0,FMTID1,Offset0,Offset1;blob.chk("feff","Byte Order: ");var vers=blob.read_shift(2);var SystemIdentifier=blob.read_shift(4);blob.chk(CFB.utils.consts.HEADER_CLSID,"CLSID: ");NumSets=blob.read_shift(4);if(NumSets!==1&&NumSets!==2)throw"Unrecognized #Sets: "+NumSets;FMTID0=blob.read_shift(16);Offset0=blob.read_shift(4);if(NumSets===1&&Offset0!==blob.l)throw"Length mismatch";else if(NumSets===2){FMTID1=blob.read_shift(16);Offset1=blob.read_shift(4)}var PSet0=parse_PropertySet(blob,PIDSI);var rval={SystemIdentifier:SystemIdentifier};for(var y in PSet0)rval[y]=PSet0[y];rval.FMTID=FMTID0;if(NumSets===1)return rval;if(blob.l!==Offset1)throw"Length mismatch 2: "+blob.l+" !== "+Offset1;var PSet1;try{PSet1=parse_PropertySet(blob,null)}catch(e){}for(y in PSet1)rval[y]=PSet1[y];rval.FMTID=[FMTID0,FMTID1];return rval}var DO_NOT_EXPORT_CFB=true;var CFB=function _CFB(){var exports={};exports.version="0.10.0";function parse(file){var mver=3;var ssz=512;var nmfs=0;var ndfs=0;var dir_start=0;var minifat_start=0;var difat_start=0;var fat_addrs=[];var blob=file.slice(0,512);prep_blob(blob,0);mver=check_get_mver(blob);switch(mver){case 3:ssz=512;break;case 4:ssz=4096;break;default:throw"Major Version: Expected 3 or 4 saw "+mver}if(ssz!==512){blob=file.slice(0,ssz);prep_blob(blob,28)}var header=file.slice(0,ssz);check_shifts(blob,mver);var nds=blob.read_shift(4,"i");if(mver===3&&nds!==0)throw"# Directory Sectors: Expected 0 saw "+nds;blob.l+=4;dir_start=blob.read_shift(4,"i");blob.l+=4;blob.chk("00100000","Mini Stream Cutoff Size: ");minifat_start=blob.read_shift(4,"i");nmfs=blob.read_shift(4,"i");difat_start=blob.read_shift(4,"i");ndfs=blob.read_shift(4,"i");for(var q,j=0;j<109;++j){q=blob.read_shift(4,"i");if(q<0)break;fat_addrs[j]=q}var sectors=sectorify(file,ssz);sleuth_fat(difat_start,ndfs,sectors,ssz,fat_addrs);var sector_list=make_sector_list(sectors,dir_start,fat_addrs,ssz);sector_list[dir_start].name="!Directory";if(nmfs>0&&minifat_start!==ENDOFCHAIN)sector_list[minifat_start].name="!MiniFAT";sector_list[fat_addrs[0]].name="!FAT";var files={},Paths=[],FileIndex=[],FullPaths=[],FullPathDir={};read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex);build_full_paths(FileIndex,FullPathDir,FullPaths,Paths);var root_name=Paths.shift();Paths.root=root_name;var find_path=make_find_path(FullPaths,Paths,FileIndex,files,root_name);return{raw:{header:header,sectors:sectors},FileIndex:FileIndex,FullPaths:FullPaths,FullPathDir:FullPathDir,find:find_path}}function check_get_mver(blob){blob.chk(HEADER_SIGNATURE,"Header Signature: ");blob.chk(HEADER_CLSID,"CLSID: ");blob.l+=2;return blob.read_shift(2,"u")}function check_shifts(blob,mver){var shift=9;blob.chk("feff","Byte Order: ");switch(shift=blob.read_shift(2)){case 9:if(mver!==3)throw"MajorVersion/SectorShift Mismatch";break;case 12:if(mver!==4)throw"MajorVersion/SectorShift Mismatch";break;default:throw"Sector Shift: Expected 9 or 12 saw "+shift}blob.chk("0600","Mini Sector Shift: ");blob.chk("000000000000","Reserved: ")}function sectorify(file,ssz){var nsectors=Math.ceil(file.length/ssz)-1;var sectors=new Array(nsectors);for(var i=1;i<nsectors;++i)sectors[i-1]=file.slice(i*ssz,(i+1)*ssz);sectors[nsectors-1]=file.slice(nsectors*ssz);return sectors}function build_full_paths(FI,FPD,FP,Paths){var i=0,L=0,R=0,C=0,j=0,pl=Paths.length;var dad=new Array(pl),q=new Array(pl);for(;i<pl;++i){dad[i]=q[i]=i;FP[i]=Paths[i]}for(;j<q.length;++j){i=q[j];L=FI[i].L;R=FI[i].R;C=FI[i].C;if(dad[i]===i){if(L!==-1&&dad[L]!==L)dad[i]=dad[L];if(R!==-1&&dad[R]!==R)dad[i]=dad[R]}if(C!==-1)dad[C]=i;if(L!==-1){dad[L]=dad[i];q.push(L)}if(R!==-1){dad[R]=dad[i];q.push(R)}}for(i=1;i!==pl;++i)if(dad[i]===i){if(R!==-1&&dad[R]!==R)dad[i]=dad[R];else if(L!==-1&&dad[L]!==L)dad[i]=dad[L]}for(i=1;i<pl;++i){if(FI[i].type===0)continue;j=dad[i];if(j===0)FP[i]=FP[0]+"/"+FP[i];else while(j!==0){FP[i]=FP[j]+"/"+FP[i];j=dad[j]}dad[i]=0}FP[0]+="/";for(i=1;i<pl;++i){if(FI[i].type!==2)FP[i]+="/";FPD[FP[i]]=FI[i]}}function make_find_path(FullPaths,Paths,FileIndex,files,root_name){var UCFullPaths=new Array(FullPaths.length);var UCPaths=new Array(Paths.length),i;for(i=0;i<FullPaths.length;++i)UCFullPaths[i]=FullPaths[i].toUpperCase();for(i=0;i<Paths.length;++i)UCPaths[i]=Paths[i].toUpperCase();return function find_path(path){var k;if(path.charCodeAt(0)===47){k=true;path=root_name+path}else k=path.indexOf("/")!==-1;var UCPath=path.toUpperCase();var w=k===true?UCFullPaths.indexOf(UCPath):UCPaths.indexOf(UCPath);if(w===-1)return null;return k===true?FileIndex[w]:files[Paths[w]]}}function sleuth_fat(idx,cnt,sectors,ssz,fat_addrs){var q;if(idx===ENDOFCHAIN){if(cnt!==0)throw"DIFAT chain shorter than expected"}else if(idx!==-1){var sector=sectors[idx],m=(ssz>>>2)-1;for(var i=0;i<m;++i){if((q=__readInt32LE(sector,i*4))===ENDOFCHAIN)break;fat_addrs.push(q)}sleuth_fat(__readInt32LE(sector,ssz-4),cnt-1,sectors,ssz,fat_addrs)}}function make_sector_list(sectors,dir_start,fat_addrs,ssz){var sl=sectors.length,sector_list=new Array(sl);var chkd=new Array(sl),buf,buf_chain;var modulus=ssz-1,i,j,k,jj;for(i=0;i<sl;++i){buf=[];k=i+dir_start;if(k>=sl)k-=sl;if(chkd[k]===true)continue;buf_chain=[];for(j=k;j>=0;){chkd[j]=true;buf[buf.length]=j;buf_chain.push(sectors[j]);var addr=fat_addrs[Math.floor(j*4/ssz)];jj=j*4&modulus;if(ssz<4+jj)throw"FAT boundary crossed: "+j+" 4 "+ssz;j=__readInt32LE(sectors[addr],jj)}sector_list[k]={nodes:buf,data:__toBuffer([buf_chain])}}return sector_list}function read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex){var blob;var minifat_store=0,pl=Paths.length?2:0;var sector=sector_list[dir_start].data;var i=0,namelen=0,name,o,ctime,mtime;for(;i<sector.length;i+=128){blob=sector.slice(i,i+128);prep_blob(blob,64);namelen=blob.read_shift(2);if(namelen===0)continue;name=__utf16le(blob,0,namelen-pl).replace(chr0,"").replace(chr1,"!");Paths.push(name);o={name:name,type:blob.read_shift(1),color:blob.read_shift(1),L:blob.read_shift(4,"i"),R:blob.read_shift(4,"i"),C:blob.read_shift(4,"i"),clsid:blob.read_shift(16),state:blob.read_shift(4,"i")};ctime=blob.read_shift(2)+blob.read_shift(2)+blob.read_shift(2)+blob.read_shift(2);if(ctime!==0){o.ctime=ctime;o.ct=read_date(blob,blob.l-8)}mtime=blob.read_shift(2)+blob.read_shift(2)+blob.read_shift(2)+blob.read_shift(2);if(mtime!==0){o.mtime=mtime;o.mt=read_date(blob,blob.l-8)}o.start=blob.read_shift(4,"i");o.size=blob.read_shift(4,"i");if(o.type===5){minifat_store=o.start;if(nmfs>0&&minifat_store!==ENDOFCHAIN)sector_list[minifat_store].name="!StreamData"}else if(o.size>=4096){o.storage="fat";if(sector_list[o.start]===undefined)if((o.start+=dir_start)>=sectors.length)o.start-=sectors.length;sector_list[o.start].name=o.name;o.content=sector_list[o.start].data.slice(0,o.size);prep_blob(o.content,0)}else{o.storage="minifat";if(minifat_store!==ENDOFCHAIN&&o.start!==ENDOFCHAIN){o.content=sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size);prep_blob(o.content,0)}}files[name]=o;FileIndex.push(o)}}function read_date(blob,offset){return new Date((__readUInt32LE(blob,offset+4)/1e7*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7-11644473600)*1e3)}var fs;function readFileSync(filename){if(fs===undefined)fs=require("fs");return parse(fs.readFileSync(filename))}function readSync(blob,options){switch(options!==undefined&&options.type!==undefined?options.type:"base64"){case"file":return readFileSync(blob);case"base64":return parse(s2a(Base64.decode(blob)));case"binary":return parse(s2a(blob))}return parse(blob)}var MSSZ=64;var ENDOFCHAIN=-2;var HEADER_SIGNATURE="d0cf11e0a1b11ae1";var HEADER_CLSID="00000000000000000000000000000000";var consts={MAXREGSECT:-6,DIFSECT:-4,FATSECT:-3,ENDOFCHAIN:ENDOFCHAIN,FREESECT:-1,HEADER_SIGNATURE:HEADER_SIGNATURE,HEADER_MINOR_VERSION:"3e00",MAXREGSID:-6,NOSTREAM:-1,HEADER_CLSID:HEADER_CLSID,EntryTypes:["unknown","storage","stream","lockbytes","property","root"]};exports.read=readSync;exports.parse=parse;exports.utils={ReadShift:ReadShift,CheckField:CheckField,prep_blob:prep_blob,bconcat:bconcat,consts:consts};return exports}();if(typeof require!=="undefined"&&typeof module!=="undefined"&&typeof DO_NOT_EXPORT_CFB==="undefined"){module.exports=CFB}function parsenoop(blob,length){blob.read_shift(length);return}function parsenoop2(blob,length){blob.read_shift(length);return null}function parslurp(blob,length,cb){var arr=[],target=blob.l+length;while(blob.l<target)arr.push(cb(blob,target-blob.l));if(target!==blob.l)throw new Error("Slurp error");return arr}function parslurp2(blob,length,cb){var arr=[],target=blob.l+length,len=blob.read_shift(2);while(len--!==0)arr.push(cb(blob,target-blob.l));if(target!==blob.l)throw new Error("Slurp error");return arr}function parsebool(blob,length){return blob.read_shift(length)===1}function parseuint16(blob){return blob.read_shift(2,"u")}function parseuint16a(blob,length){return parslurp(blob,length,parseuint16)}var parse_Boolean=parsebool;function parse_Bes(blob){var v=blob.read_shift(1),t=blob.read_shift(1);return t===1?BERR[v]:v===1}function parse_ShortXLUnicodeString(blob,length,opts){var cch=blob.read_shift(1);var width=1,encoding="sbcs";if(opts===undefined||opts.biff!==5){var fHighByte=blob.read_shift(1);if(fHighByte){width=2;encoding="dbcs"}}return cch?blob.read_shift(cch,encoding):""}function parse_XLUnicodeRichExtendedString(blob){var cch=blob.read_shift(2),flags=blob.read_shift(1);var fHighByte=flags&1,fExtSt=flags&4,fRichSt=flags&8;var width=1+(flags&1);var cRun,cbExtRst;var z={};if(fRichSt)cRun=blob.read_shift(2);if(fExtSt)cbExtRst=blob.read_shift(4);var encoding=flags&1?"dbcs":"sbcs";var msg=cch===0?"":blob.read_shift(cch,encoding);if(fRichSt)blob.l+=4*cRun;if(fExtSt)blob.l+=cbExtRst;z.t=msg;if(!fRichSt){z.raw="<t>"+z.t+"</t>";z.r=z.t}return z}function parse_XLUnicodeStringNoCch(blob,cch,opts){var retval;var fHighByte=blob.read_shift(1);if(fHighByte===0){retval=blob.read_shift(cch,"sbcs")}else{retval=blob.read_shift(cch,"dbcs")}return retval}function parse_XLUnicodeString(blob,length,opts){var cch=blob.read_shift(opts!==undefined&&opts.biff===5?1:2);if(cch===0){blob.l++;return""}return parse_XLUnicodeStringNoCch(blob,cch,opts)}function parse_XLUnicodeString2(blob,length,opts){if(opts.biff!==5)return parse_XLUnicodeString(blob,length,opts);var cch=blob.read_shift(1);if(cch===0){blob.l++;return""}return blob.read_shift(cch,"sbcs")}function parse_Xnum(blob){return blob.read_shift(8,"f")}var parse_ControlInfo=parsenoop;var parse_URLMoniker=function(blob,length){var len=blob.read_shift(4),start=blob.l;var extra=false;if(len>24){blob.l+=len-24;if(blob.read_shift(16)==="795881f43b1d7f48af2c825dc4852763")extra=true;blob.l=start}var url=blob.read_shift((extra?len-24:len)>>1,"utf16le").replace(chr0,"");if(extra)blob.l+=24;return url};var parse_FileMoniker=function(blob,length){var cAnti=blob.read_shift(2);var ansiLength=blob.read_shift(4);var ansiPath=blob.read_shift(ansiLength,"cstr");var endServer=blob.read_shift(2);var versionNumber=blob.read_shift(2);var cbUnicodePathSize=blob.read_shift(4);if(cbUnicodePathSize===0)return ansiPath.replace(/\\/g,"/");var cbUnicodePathBytes=blob.read_shift(4);var usKeyValue=blob.read_shift(2);var unicodePath=blob.read_shift(cbUnicodePathBytes>>1,"utf16le").replace(chr0,"");return unicodePath};var parse_HyperlinkMoniker=function(blob,length){var clsid=blob.read_shift(16);length-=16;switch(clsid){case"e0c9ea79f9bace118c8200aa004ba90b":return parse_URLMoniker(blob,length);case"0303000000000000c000000000000046":return parse_FileMoniker(blob,length);default:throw"unsupported moniker "+clsid}};var parse_HyperlinkString=function(blob,length){var len=blob.read_shift(4);var o=blob.read_shift(len,"utf16le").replace(chr0,"");return o};var parse_Hyperlink=function(blob,length){var end=blob.l+length;var sVer=blob.read_shift(4);if(sVer!==2)throw new Error("Unrecognized streamVersion: "+sVer);var flags=blob.read_shift(2);blob.l+=2;var displayName,targetFrameName,moniker,oleMoniker,location,guid,fileTime;if(flags&16)displayName=parse_HyperlinkString(blob,end-blob.l);if(flags&128)targetFrameName=parse_HyperlinkString(blob,end-blob.l);if((flags&257)===257)moniker=parse_HyperlinkString(blob,end-blob.l);if((flags&257)===1)oleMoniker=parse_HyperlinkMoniker(blob,end-blob.l);if(flags&8)location=parse_HyperlinkString(blob,end-blob.l);if(flags&32)guid=blob.read_shift(16);if(flags&64)fileTime=parse_FILETIME(blob,8);blob.l=end;var target=targetFrameName||moniker||oleMoniker;if(location)target+="#"+location;return{Target:target}};function isval(x){return x!==undefined&&x!==null}function keys(o){return Object.keys(o)}function evert(obj,arr){var o={};var K=keys(obj);for(var i=0;i<K.length;++i){var k=K[i];if(!arr)o[obj[k]]=k;else(o[obj[k]]=o[obj[k]]||[]).push(k)}return o}function parse_Cell(blob,length){var rw=blob.read_shift(2);var col=blob.read_shift(2);var ixfe=blob.read_shift(2);return{r:rw,c:col,ixfe:ixfe}}function parse_frtHeader(blob){var rt=blob.read_shift(2);var flags=blob.read_shift(2);blob.l+=8;return{type:rt,flags:flags}}function parse_OptXLUnicodeString(blob,length,opts){return length===0?"":parse_XLUnicodeString2(blob,length,opts)}var HIDEOBJENUM=["SHOWALL","SHOWPLACEHOLDER","HIDEALL"];var parse_HideObjEnum=parseuint16;function parse_XTI(blob,length){var iSupBook=blob.read_shift(2),itabFirst=blob.read_shift(2,"i"),itabLast=blob.read_shift(2,"i");return[iSupBook,itabFirst,itabLast]}function parse_RkNumber(blob){var b=blob.slice(blob.l,blob.l+4);var fX100=b[0]&1,fInt=b[0]&2;blob.l+=4;b[0]&=~3;var RK=fInt===0?__double([0,0,0,0,b[0],b[1],b[2],b[3]],0):__readInt32LE(b,0)>>2;return fX100?RK/100:RK}function parse_RkRec(blob,length){var ixfe=blob.read_shift(2);var RK=parse_RkNumber(blob);return[ixfe,RK]}function parse_AddinUdf(blob,length){blob.l+=4;length-=4;var l=blob.l+length;var udfName=parse_ShortXLUnicodeString(blob,length);var cb=blob.read_shift(2);l-=blob.l;if(cb!==l)throw"Malformed AddinUdf: padding = "+l+" != "+cb;blob.l+=cb;return udfName}function parse_Ref8U(blob,length){var rwFirst=blob.read_shift(2);var rwLast=blob.read_shift(2);var colFirst=blob.read_shift(2);var colLast=blob.read_shift(2);return{s:{c:colFirst,r:rwFirst},e:{c:colLast,r:rwLast}}}function parse_RefU(blob,length){var rwFirst=blob.read_shift(2);var rwLast=blob.read_shift(2);var colFirst=blob.read_shift(1);var colLast=blob.read_shift(1);return{s:{c:colFirst,r:rwFirst},e:{c:colLast,r:rwLast}}}var parse_Ref=parse_RefU;function parse_FtCmo(blob,length){blob.l+=4;var ot=blob.read_shift(2);var id=blob.read_shift(2);var flags=blob.read_shift(2);blob.l+=12;return[id,ot,flags]}function parse_FtNts(blob,length){var out={};blob.l+=4;blob.l+=16;out.fSharedNote=blob.read_shift(2);blob.l+=4;return out}function parse_FtCf(blob,length){var out={};blob.l+=4;blob.cf=blob.read_shift(2);return out}var FtTab={21:parse_FtCmo,19:parsenoop,18:function(blob,length){blob.l+=12},17:function(blob,length){blob.l+=8},16:parsenoop,15:parsenoop,13:parse_FtNts,12:function(blob,length){blob.l+=24},11:function(blob,length){blob.l+=10},10:function(blob,length){blob.l+=16},9:parsenoop,8:function(blob,length){blob.l+=6},7:parse_FtCf,6:function(blob,length){blob.l+=6},4:parsenoop,0:function(blob,length){blob.l+=4}};function parse_FtArray(blob,length,ot){var s=blob.l;var fts=[];while(blob.l<s+length){var ft=blob.read_shift(2);blob.l-=2;try{fts.push(FtTab[ft](blob,s+length-blob.l))}catch(e){blob.l=s+length;return fts}}if(blob.l!=s+length)blob.l=s+length;return fts}var parse_FontIndex=parseuint16;function parse_BOF(blob,length){var o={};o.BIFFVer=blob.read_shift(2);length-=2;if(o.BIFFVer!==1536&&o.BIFFVer!==1280)throw"Unexpected BIFF Ver "+o.BIFFVer;blob.read_shift(length);return o}function parse_InterfaceHdr(blob,length){if(length===0)return 1200;var q;if((q=blob.read_shift(2))!==1200)throw"InterfaceHdr codePage "+q;return 1200}function parse_WriteAccess(blob,length,opts){if(opts.enc){blob.l+=length;return""}var l=blob.l;var UserName=parse_XLUnicodeString(blob,0,opts);blob.read_shift(length+l-blob.l);return UserName}function parse_BoundSheet8(blob,length,opts){var pos=blob.read_shift(4);var hidden=blob.read_shift(1)>>6;var dt=blob.read_shift(1);switch(dt){case 0:dt="Worksheet";break;case 1:dt="Macrosheet";break;case 2:dt="Chartsheet";break;case 6:dt="VBAModule";break}var name=parse_ShortXLUnicodeString(blob,0,opts);return{pos:pos,hs:hidden,dt:dt,name:name}}function parse_SST(blob,length){var cnt=blob.read_shift(4);var ucnt=blob.read_shift(4);var strs=[];for(var i=0;i!=ucnt;++i){strs.push(parse_XLUnicodeRichExtendedString(blob))}strs.Count=cnt;strs.Unique=ucnt;return strs}function parse_ExtSST(blob,length){var extsst={};extsst.dsst=blob.read_shift(2);blob.l+=length-2;return extsst}function parse_Row(blob,length){var rw=blob.read_shift(2),col=blob.read_shift(2),Col=blob.read_shift(2),rht=blob.read_shift(2);blob.read_shift(4);var flags=blob.read_shift(1);blob.read_shift(1);blob.read_shift(2);return{r:rw,c:col,cnt:Col-col}}function parse_ForceFullCalculation(blob,length){var header=parse_frtHeader(blob);if(header.type!=2211)throw"Invalid Future Record "+header.type;var fullcalc=blob.read_shift(4);return fullcalc!==0}var parse_CompressPictures=parsenoop2;function parse_RecalcId(blob,length){blob.read_shift(2);return blob.read_shift(4)}function parse_DefaultRowHeight(blob,length){var f=blob.read_shift(2),miyRw;miyRw=blob.read_shift(2);var fl={Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};return[fl,miyRw]}function parse_Window1(blob,length){var xWn=blob.read_shift(2),yWn=blob.read_shift(2),dxWn=blob.read_shift(2),dyWn=blob.read_shift(2);var flags=blob.read_shift(2),iTabCur=blob.read_shift(2),iTabFirst=blob.read_shift(2);var ctabSel=blob.read_shift(2),wTabRatio=blob.read_shift(2);return{Pos:[xWn,yWn],Dim:[dxWn,dyWn],Flags:flags,CurTab:iTabCur,FirstTab:iTabFirst,Selected:ctabSel,TabRatio:wTabRatio}}function parse_Font(blob,length,opts){blob.l+=14;var name=parse_ShortXLUnicodeString(blob,0,opts);return name}function parse_LabelSst(blob,length){var cell=parse_Cell(blob);cell.isst=blob.read_shift(4);return cell}function parse_Label(blob,length,opts){var cell=parse_Cell(blob,6);var str=parse_XLUnicodeString(blob,length-6,opts);cell.val=str;return cell}function parse_Format(blob,length,opts){var ifmt=blob.read_shift(2);var fmtstr=parse_XLUnicodeString2(blob,0,opts);return[ifmt,fmtstr]}function parse_Dimensions(blob,length){var w=length===10?2:4;var r=blob.read_shift(w),R=blob.read_shift(w),c=blob.read_shift(2),C=blob.read_shift(2);blob.l+=2;return{s:{r:r,c:c},e:{r:R,c:C}}}function parse_RK(blob,length){var rw=blob.read_shift(2),col=blob.read_shift(2);var rkrec=parse_RkRec(blob);return{r:rw,c:col,ixfe:rkrec[0],rknum:rkrec[1]}}function parse_MulRk(blob,length){var target=blob.l+length-2;var rw=blob.read_shift(2),col=blob.read_shift(2);var rkrecs=[];while(blob.l<target)rkrecs.push(parse_RkRec(blob));if(blob.l!==target)throw"MulRK read error";var lastcol=blob.read_shift(2);if(rkrecs.length!=lastcol-col+1)throw"MulRK length mismatch";return{r:rw,c:col,C:lastcol,rkrec:rkrecs}}var parse_CellXF=parsenoop;var parse_StyleXF=parsenoop;function parse_XF(blob,length){var o={};o.ifnt=blob.read_shift(2);o.ifmt=blob.read_shift(2);o.flags=blob.read_shift(2);o.fStyle=o.flags>>2&1;length-=6;o.data=o.fStyle?parse_StyleXF(blob,length):parse_CellXF(blob,length);return o}function parse_Guts(blob,length){blob.l+=4;var out=[blob.read_shift(2),blob.read_shift(2)];if(out[0]!==0)out[0]--;if(out[1]!==0)out[1]--;if(out[0]>7||out[1]>7)throw"Bad Gutters: "+out;return out}function parse_BoolErr(blob,length){var cell=parse_Cell(blob,6);var val=parse_Bes(blob,2);cell.val=val;cell.t=val===true||val===false?"b":"e";return cell}function parse_Number(blob,length){var cell=parse_Cell(blob,6);var xnum=parse_Xnum(blob,8);cell.val=xnum;return cell}var parse_XLHeaderFooter=parse_OptXLUnicodeString;function parse_SupBook(blob,length,opts){var end=blob.l+length;var ctab=blob.read_shift(2);var cch=blob.read_shift(2);var virtPath;if(cch>=1&&cch<=255)virtPath=parse_XLUnicodeStringNoCch(blob,cch);var rgst=blob.read_shift(end-blob.l);opts.sbcch=cch;return[cch,ctab,virtPath,rgst]}function parse_ExternName(blob,length,opts){var flags=blob.read_shift(2);var body;var o={fBuiltIn:flags&1,fWantAdvise:flags>>>1&1,fWantPict:flags>>>2&1,fOle:flags>>>3&1,fOleLink:flags>>>4&1,cf:flags>>>5&1023,fIcon:flags>>>15&1};if(opts.sbcch===14849)body=parse_AddinUdf(blob,length-2);o.body=body||blob.read_shift(length-2);return o}function parse_Lbl(blob,length,opts){if(opts.biff<8)return parse_Label(blob,length,opts);var target=blob.l+length;var flags=blob.read_shift(2);var chKey=blob.read_shift(1);var cch=blob.read_shift(1);var cce=blob.read_shift(2);blob.l+=2;var itab=blob.read_shift(2);blob.l+=4;var name=parse_XLUnicodeStringNoCch(blob,cch,opts);var rgce=parse_NameParsedFormula(blob,target-blob.l,opts,cce);return{chKey:chKey,Name:name,rgce:rgce}}function parse_ExternSheet(blob,length,opts){if(opts.biff<8)return parse_ShortXLUnicodeString(blob,length,opts);var o=parslurp2(blob,length,parse_XTI);var oo=[];if(opts.sbcch===1025){for(var i=0;i!=o.length;++i)oo.push(opts.snames[o[i][1]]);return oo}else return o}function parse_ShrFmla(blob,length,opts){var ref=parse_RefU(blob,6);blob.l++;var cUse=blob.read_shift(1);length-=8;return[parse_SharedParsedFormula(blob,length,opts),cUse]}function parse_Array(blob,length,opts){var ref=parse_Ref(blob,6);blob.l+=6;length-=12;return[ref,parse_ArrayParsedFormula(blob,length,opts,ref)]}function parse_MTRSettings(blob,length){var fMTREnabled=blob.read_shift(4)!==0;var fUserSetThreadCount=blob.read_shift(4)!==0;var cUserThreadCount=blob.read_shift(4);return[fMTREnabled,fUserSetThreadCount,cUserThreadCount]}function parse_NoteSh(blob,length,opts){if(opts.biff<8)return;var row=blob.read_shift(2),col=blob.read_shift(2);var flags=blob.read_shift(2),idObj=blob.read_shift(2);var stAuthor=parse_XLUnicodeString2(blob,0,opts);if(opts.biff<8)blob.read_shift(1);return[{r:row,c:col},stAuthor,idObj,flags]}function parse_Note(blob,length,opts){return parse_NoteSh(blob,length,opts)}function parse_MergeCells(blob,length){var merges=[];var cmcs=blob.read_shift(2);while(cmcs--)merges.push(parse_Ref8U(blob,length));return merges}function parse_Obj(blob,length){var cmo=parse_FtCmo(blob,22);var fts=parse_FtArray(blob,length-22,cmo[1]);return{cmo:cmo,ft:fts}}function parse_TxO(blob,length,opts){var s=blob.l;try{blob.l+=4;var ot=(opts.lastobj||{cmo:[0,0]}).cmo[1];var controlInfo;if([0,5,7,11,12,14].indexOf(ot)==-1)blob.l+=6;else controlInfo=parse_ControlInfo(blob,6,opts);var cchText=blob.read_shift(2);var cbRuns=blob.read_shift(2);var ifntEmpty=parse_FontIndex(blob,2);var len=blob.read_shift(2);blob.l+=len;var texts="";for(var i=1;i<blob.lens.length-1;++i){if(blob.l-s!=blob.lens[i])throw"TxO: bad continue record";var hdr=blob[blob.l];var t=parse_XLUnicodeStringNoCch(blob,blob.lens[i+1]-blob.lens[i]-1);texts+=t;if(texts.length>=(hdr?cchText:2*cchText))break}if(texts.length!==cchText&&texts.length!==cchText*2){throw"cchText: "+cchText+" != "+texts.length}blob.l=s+length;return{t:texts}}catch(e){blob.l=s+length;return{t:texts||""}}}var parse_HLink=function(blob,length){var ref=parse_Ref8U(blob,8);blob.l+=16;var hlink=parse_Hyperlink(blob,length-24);return[ref,hlink]};var parse_HLinkTooltip=function(blob,length){var end=blob.l+length;blob.read_shift(2);var ref=parse_Ref8U(blob,8);var wzTooltip=blob.read_shift((length-10)/2,"dbcs");wzTooltip=wzTooltip.replace(chr0,"");return[ref,wzTooltip]};function parse_Country(blob,length){var o=[],d;d=blob.read_shift(2);o[0]=CountryEnum[d]||d;d=blob.read_shift(2);o[1]=CountryEnum[d]||d;return o}var parse_Backup=parsebool;var parse_Blank=parse_Cell;var parse_BottomMargin=parse_Xnum;var parse_BuiltInFnGroupCount=parseuint16;var parse_CalcCount=parseuint16;var parse_CalcDelta=parse_Xnum;var parse_CalcIter=parsebool;var parse_CalcMode=parseuint16;var parse_CalcPrecision=parsebool;var parse_CalcRefMode=parsenoop2;var parse_CalcSaveRecalc=parsebool;var parse_CodePage=parseuint16;var parse_Compat12=parsebool;var parse_Date1904=parsebool;var parse_DefColWidth=parseuint16;var parse_DSF=parsenoop2;var parse_EntExU2=parsenoop2;var parse_EOF=parsenoop2;var parse_Excel9File=parsenoop2;var parse_FeatHdr=parsenoop2;var parse_FontX=parseuint16;var parse_Footer=parse_XLHeaderFooter;var parse_GridSet=parseuint16;var parse_HCenter=parsebool;var parse_Header=parse_XLHeaderFooter;var parse_HideObj=parse_HideObjEnum;var parse_InterfaceEnd=parsenoop2;var parse_LeftMargin=parse_Xnum;var parse_Mms=parsenoop2;var parse_ObjProtect=parsebool;var parse_Password=parseuint16;var parse_PrintGrid=parsebool;var parse_PrintRowCol=parsebool;var parse_PrintSize=parseuint16;var parse_Prot4Rev=parsebool;var parse_Prot4RevPass=parseuint16;var parse_Protect=parsebool;var parse_RefreshAll=parsebool;var parse_RightMargin=parse_Xnum;
18560 var parse_RRTabId=parseuint16a;var parse_ScenarioProtect=parsebool;var parse_Scl=parseuint16a;var parse_String=parse_XLUnicodeString;var parse_SxBool=parsebool;var parse_TopMargin=parse_Xnum;var parse_UsesELFs=parsebool;var parse_VCenter=parsebool;var parse_WinProtect=parsebool;var parse_WriteProtect=parsenoop;var parse_VerticalPageBreaks=parsenoop;var parse_HorizontalPageBreaks=parsenoop;var parse_Selection=parsenoop;var parse_Continue=parsenoop;var parse_Pane=parsenoop;var parse_Pls=parsenoop;var parse_DCon=parsenoop;var parse_DConRef=parsenoop;var parse_DConName=parsenoop;var parse_XCT=parsenoop;var parse_CRN=parsenoop;var parse_FileSharing=parsenoop;var parse_Uncalced=parsenoop;var parse_Template=parsenoop;var parse_Intl=parsenoop;var parse_ColInfo=parsenoop;var parse_WsBool=parsenoop;var parse_Sort=parsenoop;var parse_Palette=parsenoop;var parse_Sync=parsenoop;var parse_LPr=parsenoop;var parse_DxGCol=parsenoop;var parse_FnGroupName=parsenoop;var parse_FilterMode=parsenoop;var parse_AutoFilterInfo=parsenoop;var parse_AutoFilter=parsenoop;var parse_Setup=parsenoop;var parse_ScenMan=parsenoop;var parse_SCENARIO=parsenoop;var parse_SxView=parsenoop;var parse_Sxvd=parsenoop;var parse_SXVI=parsenoop;var parse_SxIvd=parsenoop;var parse_SXLI=parsenoop;var parse_SXPI=parsenoop;var parse_DocRoute=parsenoop;var parse_RecipName=parsenoop;var parse_MulBlank=parsenoop;var parse_SXDI=parsenoop;var parse_SXDB=parsenoop;var parse_SXFDB=parsenoop;var parse_SXDBB=parsenoop;var parse_SXNum=parsenoop;var parse_SxErr=parsenoop;var parse_SXInt=parsenoop;var parse_SXString=parsenoop;var parse_SXDtr=parsenoop;var parse_SxNil=parsenoop;var parse_SXTbl=parsenoop;var parse_SXTBRGIITM=parsenoop;var parse_SxTbpg=parsenoop;var parse_ObProj=parsenoop;var parse_SXStreamID=parsenoop;var parse_DBCell=parsenoop;var parse_SXRng=parsenoop;var parse_SxIsxoper=parsenoop;var parse_BookBool=parsenoop;var parse_DbOrParamQry=parsenoop;var parse_OleObjectSize=parsenoop;var parse_SXVS=parsenoop;var parse_BkHim=parsenoop;var parse_MsoDrawingGroup=parsenoop;var parse_MsoDrawing=parsenoop;var parse_MsoDrawingSelection=parsenoop;var parse_PhoneticInfo=parsenoop;var parse_SxRule=parsenoop;var parse_SXEx=parsenoop;var parse_SxFilt=parsenoop;var parse_SxDXF=parsenoop;var parse_SxItm=parsenoop;var parse_SxName=parsenoop;var parse_SxSelect=parsenoop;var parse_SXPair=parsenoop;var parse_SxFmla=parsenoop;var parse_SxFormat=parsenoop;var parse_SXVDEx=parsenoop;var parse_SXFormula=parsenoop;var parse_SXDBEx=parsenoop;var parse_RRDInsDel=parsenoop;var parse_RRDHead=parsenoop;var parse_RRDChgCell=parsenoop;var parse_RRDRenSheet=parsenoop;var parse_RRSort=parsenoop;var parse_RRDMove=parsenoop;var parse_RRFormat=parsenoop;var parse_RRAutoFmt=parsenoop;var parse_RRInsertSh=parsenoop;var parse_RRDMoveBegin=parsenoop;var parse_RRDMoveEnd=parsenoop;var parse_RRDInsDelBegin=parsenoop;var parse_RRDInsDelEnd=parsenoop;var parse_RRDConflict=parsenoop;var parse_RRDDefName=parsenoop;var parse_RRDRstEtxp=parsenoop;var parse_LRng=parsenoop;var parse_CUsr=parsenoop;var parse_CbUsr=parsenoop;var parse_UsrInfo=parsenoop;var parse_UsrExcl=parsenoop;var parse_FileLock=parsenoop;var parse_RRDInfo=parsenoop;var parse_BCUsrs=parsenoop;var parse_UsrChk=parsenoop;var parse_UserBView=parsenoop;var parse_UserSViewBegin=parsenoop;var parse_UserSViewEnd=parsenoop;var parse_RRDUserView=parsenoop;var parse_Qsi=parsenoop;var parse_CondFmt=parsenoop;var parse_CF=parsenoop;var parse_DVal=parsenoop;var parse_DConBin=parsenoop;var parse_Lel=parsenoop;var parse_CodeName=parse_XLUnicodeString;var parse_SXFDBType=parsenoop;var parse_ObNoMacros=parsenoop;var parse_Dv=parsenoop;var parse_Index=parsenoop;var parse_Table=parsenoop;var parse_Window2=parsenoop;var parse_Style=parsenoop;var parse_BigName=parsenoop;var parse_ContinueBigName=parsenoop;var parse_WebPub=parsenoop;var parse_QsiSXTag=parsenoop;var parse_DBQueryExt=parsenoop;var parse_ExtString=parsenoop;var parse_TxtQry=parsenoop;var parse_Qsir=parsenoop;var parse_Qsif=parsenoop;var parse_RRDTQSIF=parsenoop;var parse_OleDbConn=parsenoop;var parse_WOpt=parsenoop;var parse_SXViewEx=parsenoop;var parse_SXTH=parsenoop;var parse_SXPIEx=parsenoop;var parse_SXVDTEx=parsenoop;var parse_SXViewEx9=parsenoop;var parse_ContinueFrt=parsenoop;var parse_RealTimeData=parsenoop;var parse_ChartFrtInfo=parsenoop;var parse_FrtWrapper=parsenoop;var parse_StartBlock=parsenoop;var parse_EndBlock=parsenoop;var parse_StartObject=parsenoop;var parse_EndObject=parsenoop;var parse_CatLab=parsenoop;var parse_YMult=parsenoop;var parse_SXViewLink=parsenoop;var parse_PivotChartBits=parsenoop;var parse_FrtFontList=parsenoop;var parse_SheetExt=parsenoop;var parse_BookExt=parsenoop;var parse_SXAddl=parsenoop;var parse_CrErr=parsenoop;var parse_HFPicture=parsenoop;var parse_Feat=parsenoop;var parse_DataLabExt=parsenoop;var parse_DataLabExtContents=parsenoop;var parse_CellWatch=parsenoop;var parse_FeatHdr11=parsenoop;var parse_Feature11=parsenoop;var parse_DropDownObjIds=parsenoop;var parse_ContinueFrt11=parsenoop;var parse_DConn=parsenoop;var parse_List12=parsenoop;var parse_Feature12=parsenoop;var parse_CondFmt12=parsenoop;var parse_CF12=parsenoop;var parse_CFEx=parsenoop;var parse_XFCRC=parsenoop;var parse_XFExt=parsenoop;var parse_AutoFilter12=parsenoop;var parse_ContinueFrt12=parsenoop;var parse_MDTInfo=parsenoop;var parse_MDXStr=parsenoop;var parse_MDXTuple=parsenoop;var parse_MDXSet=parsenoop;var parse_MDXProp=parsenoop;var parse_MDXKPI=parsenoop;var parse_MDB=parsenoop;var parse_PLV=parsenoop;var parse_DXF=parsenoop;var parse_TableStyles=parsenoop;var parse_TableStyle=parsenoop;var parse_TableStyleElement=parsenoop;var parse_StyleExt=parsenoop;var parse_NamePublish=parsenoop;var parse_NameCmt=parsenoop;var parse_SortData=parsenoop;var parse_Theme=parsenoop;var parse_GUIDTypeLib=parsenoop;var parse_FnGrp12=parsenoop;var parse_NameFnGrp12=parsenoop;var parse_HeaderFooter=parsenoop;var parse_CrtLayout12=parsenoop;var parse_CrtMlFrt=parsenoop;var parse_CrtMlFrtContinue=parsenoop;var parse_ShapePropsStream=parsenoop;var parse_TextPropsStream=parsenoop;var parse_RichTextStream=parsenoop;var parse_CrtLayout12A=parsenoop;var parse_Units=parsenoop;var parse_Chart=parsenoop;var parse_Series=parsenoop;var parse_DataFormat=parsenoop;var parse_LineFormat=parsenoop;var parse_MarkerFormat=parsenoop;var parse_AreaFormat=parsenoop;var parse_PieFormat=parsenoop;var parse_AttachedLabel=parsenoop;var parse_SeriesText=parsenoop;var parse_ChartFormat=parsenoop;var parse_Legend=parsenoop;var parse_SeriesList=parsenoop;var parse_Bar=parsenoop;var parse_Line=parsenoop;var parse_Pie=parsenoop;var parse_Area=parsenoop;var parse_Scatter=parsenoop;var parse_CrtLine=parsenoop;var parse_Axis=parsenoop;var parse_Tick=parsenoop;var parse_ValueRange=parsenoop;var parse_CatSerRange=parsenoop;var parse_AxisLine=parsenoop;var parse_CrtLink=parsenoop;var parse_DefaultText=parsenoop;var parse_Text=parsenoop;var parse_ObjectLink=parsenoop;var parse_Frame=parsenoop;var parse_Begin=parsenoop;var parse_End=parsenoop;var parse_PlotArea=parsenoop;var parse_Chart3d=parsenoop;var parse_PicF=parsenoop;var parse_DropBar=parsenoop;var parse_Radar=parsenoop;var parse_Surf=parsenoop;var parse_RadarArea=parsenoop;var parse_AxisParent=parsenoop;var parse_LegendException=parsenoop;var parse_ShtProps=parsenoop;var parse_SerToCrt=parsenoop;var parse_AxesUsed=parsenoop;var parse_SBaseRef=parsenoop;var parse_SerParent=parsenoop;var parse_SerAuxTrend=parsenoop;var parse_IFmtRecord=parsenoop;var parse_Pos=parsenoop;var parse_AlRuns=parsenoop;var parse_BRAI=parsenoop;var parse_SerAuxErrBar=parsenoop;var parse_ClrtClient=parsenoop;var parse_SerFmt=parsenoop;var parse_Chart3DBarShape=parsenoop;var parse_Fbi=parsenoop;var parse_BopPop=parsenoop;var parse_AxcExt=parsenoop;var parse_Dat=parsenoop;var parse_PlotGrowth=parsenoop;var parse_SIIndex=parsenoop;var parse_GelFrame=parsenoop;var parse_BopPopCustom=parsenoop;var parse_Fbi2=parsenoop;function parse_BIFF5String(blob){var len=blob.read_shift(1);return blob.read_shift(len,"sbcs")}var _chr=function(c){return String.fromCharCode(c)};var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;var attregex=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;function parsexmltag(tag,skip_root){var words=tag.split(/\s+/);var z=[];if(!skip_root)z[0]=words[0];if(words.length===1)return z;var m=tag.match(attregexg),y,j,w,i;if(m)for(i=0;i!=m.length;++i){y=m[i].match(attregex);if((j=y[1].indexOf(":"))===-1)z[y[1]]=y[2].substr(1,y[2].length-2);else{if(y[1].substr(0,6)==="xmlns:")w="xmlns"+y[1].substr(6);else w=y[1].substr(j+1);z[w]=y[2].substr(1,y[2].length-2)}}return z}function parsexmltagobj(tag){var words=tag.split(/\s+/);var z={};if(words.length===1)return z;var m=tag.match(attregexg),y,j,w,i;if(m)for(i=0;i!=m.length;++i){y=m[i].match(attregex);if((j=y[1].indexOf(":"))===-1)z[y[1]]=y[2].substr(1,y[2].length-2);else{if(y[1].substr(0,6)==="xmlns:")w="xmlns"+y[1].substr(6);else w=y[1].substr(j+1);z[w]=y[2].substr(1,y[2].length-2)}}return z}var encodings={"&quot;":'"',"&apos;":"'","&gt;":">","&lt;":"<","&amp;":"&"};var rencoding=evert(encodings);var rencstr="&<>'\"".split("");var XML_HEADER='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';var OFFCRYPTO={};var make_offcrypto=function(O,_crypto){var crypto;if(typeof _crypto!=="undefined")crypto=_crypto;else if(typeof require!=="undefined"){try{crypto=require("cry"+"pto")}catch(e){crypto=null}}O.rc4=function(key,data){var S=new Array(256);var c=0,i=0,j=0,t=0;for(i=0;i!=256;++i)S[i]=i;for(i=0;i!=256;++i){j=j+S[i]+key[i%key.length].charCodeAt(0)&255;t=S[i];S[i]=S[j];S[j]=t}i=j=0;out=Buffer(data.length);for(c=0;c!=data.length;++c){i=i+1&255;j=(j+S[i])%256;t=S[i];S[i]=S[j];S[j]=t;out[c]=data[c]^S[S[i]+S[j]&255]}return out};if(crypto){O.md5=function(hex){return crypto.createHash("md5").update(hex).digest("hex")}}else{O.md5=function(hex){throw"unimplemented"}}};make_offcrypto(OFFCRYPTO,typeof crypto!=="undefined"?crypto:undefined);function _JS2ANSI(str){if(typeof cptable!=="undefined")return cptable.utils.encode(1252,str);return str.split("").map(function(x){return x.charCodeAt(0)})}function parse_Version(blob,length){var o={};o.Major=blob.read_shift(2);o.Minor=blob.read_shift(2);return o}function parse_EncryptionHeader(blob,length){var o={};o.Flags=blob.read_shift(4);var tmp=blob.read_shift(4);if(tmp!==0)throw"Unrecognized SizeExtra: "+tmp;o.AlgID=blob.read_shift(4);switch(o.AlgID){case 0:case 26625:case 26126:case 26127:case 26128:break;default:throw"Unrecognized encryption algorithm: "+o.AlgID}parsenoop(blob,length-12);return o}function parse_EncryptionVerifier(blob,length){return parsenoop(blob,length)}function parse_RC4CryptoHeader(blob,length){var o={};var vers=o.EncryptionVersionInfo=parse_Version(blob,4);length-=4;if(vers.Minor!=2)throw"unrecognized minor version code: "+vers.Minor;if(vers.Major>4||vers.Major<2)throw"unrecognized major version code: "+vers.Major;o.Flags=blob.read_shift(4);length-=4;var sz=blob.read_shift(4);length-=4;o.EncryptionHeader=parse_EncryptionHeader(blob,sz);length-=sz;o.EncryptionVerifier=parse_EncryptionVerifier(blob,length);return o}function parse_RC4Header(blob,length){var o={};var vers=o.EncryptionVersionInfo=parse_Version(blob,4);length-=4;if(vers.Major!=1||vers.Minor!=1)throw"unrecognized version code "+vers.Major+" : "+vers.Minor;o.Salt=blob.read_shift(16);o.EncryptedVerifier=blob.read_shift(16);o.EncryptedVerifierHash=blob.read_shift(16);return o}function crypto_CreatePasswordVerifier_Method1(Password){var Verifier=0,PasswordArray;var PasswordDecoded=_JS2ANSI(Password);var len=PasswordDecoded.length+1,i,PasswordByte;var Intermediate1,Intermediate2,Intermediate3;PasswordArray=new_buf(len);PasswordArray[0]=PasswordDecoded.length;for(i=1;i!=len;++i)PasswordArray[i]=PasswordDecoded[i-1];for(i=len-1;i>=0;--i){PasswordByte=PasswordArray[i];Intermediate1=(Verifier&16384)===0?0:1;Intermediate2=Verifier<<1&32767;Intermediate3=Intermediate1|Intermediate2;Verifier=Intermediate3^PasswordByte}return Verifier^52811}var crypto_CreateXorArray_Method1=function(){var PadArray=[187,255,255,186,255,255,185,128,0,190,15,0,191,15,0];var InitialCode=[57840,7439,52380,33984,4364,3600,61902,12606,6258,57657,54287,34041,10252,43370,20163];var XorMatrix=[44796,19929,39858,10053,20106,40212,10761,31585,63170,64933,60267,50935,40399,11199,17763,35526,1453,2906,5812,11624,23248,885,1770,3540,7080,14160,28320,56640,55369,41139,20807,41614,21821,43642,17621,28485,56970,44341,19019,38038,14605,29210,60195,50791,40175,10751,21502,43004,24537,18387,36774,3949,7898,15796,31592,63184,47201,24803,49606,37805,14203,28406,56812,17824,35648,1697,3394,6788,13576,27152,43601,17539,35078,557,1114,2228,4456,30388,60776,51953,34243,7079,14158,28316,14128,28256,56512,43425,17251,34502,7597,13105,26210,52420,35241,883,1766,3532,4129,8258,16516,33032,4657,9314,18628];var Ror=function(Byte){return(Byte/2|Byte*128)&255};var XorRor=function(byte1,byte2){return Ror(byte1^byte2)};var CreateXorKey_Method1=function(Password){var XorKey=InitialCode[Password.length-1];var CurrentElement=104;for(var i=Password.length-1;i>=0;--i){var Char=Password[i];for(var j=0;j!=7;++j){if(Char&64)XorKey^=XorMatrix[CurrentElement];Char*=2;--CurrentElement}}return XorKey};return function(password){var Password=_JS2ANSI(password);var XorKey=CreateXorKey_Method1(Password);var Index=Password.length;var ObfuscationArray=new_buf(16);for(var i=0;i!=16;++i)ObfuscationArray[i]=0;var Temp,PasswordLastChar,PadIndex;if((Index&1)===1){Temp=XorKey>>8;ObfuscationArray[Index]=XorRor(PadArray[0],Temp);--Index;Temp=XorKey&255;PasswordLastChar=Password[Password.length-1];ObfuscationArray[Index]=XorRor(PasswordLastChar,Temp)}while(Index>0){--Index;Temp=XorKey>>8;ObfuscationArray[Index]=XorRor(Password[Index],Temp);--Index;Temp=XorKey&255;ObfuscationArray[Index]=XorRor(Password[Index],Temp)}Index=15;PadIndex=15-Password.length;while(PadIndex>0){Temp=XorKey>>8;ObfuscationArray[Index]=XorRor(PadArray[PadIndex],Temp);--Index;--PadIndex;Temp=XorKey&255;ObfuscationArray[Index]=XorRor(Password[Index],Temp);--Index;--PadIndex}return ObfuscationArray}}();var crypto_DecryptData_Method1=function(password,Data,XorArrayIndex,XorArray,O){if(!O)O=Data;if(!XorArray)XorArray=crypto_CreateXorArray_Method1(password);var Index,Value;for(Index=0;Index!=Data.length;++Index){Value=Data[Index];Value^=XorArray[XorArrayIndex];Value=(Value>>5|Value<<3)&255;O[Index]=Value;++XorArrayIndex}return[O,XorArrayIndex,XorArray]};var crypto_MakeXorDecryptor=function(password){var XorArrayIndex=0,XorArray=crypto_CreateXorArray_Method1(password);return function(Data){var O=crypto_DecryptData_Method1(null,Data,XorArrayIndex,XorArray);XorArrayIndex=O[1];return O[0]}};function parse_XORObfuscation(blob,length,opts,out){var o={key:parseuint16(blob),verificationBytes:parseuint16(blob)};if(opts.password)o.verifier=crypto_CreatePasswordVerifier_Method1(opts.password);out.valid=o.verificationBytes===o.verifier;if(out.valid)out.insitu_decrypt=crypto_MakeXorDecryptor(opts.password);return o}function parse_FilePassHeader(blob,length,oo){var o=oo||{};o.Info=blob.read_shift(2);blob.l-=2;if(o.Info===1)o.Data=parse_RC4Header(blob,length);else o.Data=parse_RC4CryptoHeader(blob,length);return o}function parse_FilePass(blob,length,opts){var o={Type:blob.read_shift(2)};if(o.Type)parse_FilePassHeader(blob,length-2,o);else parse_XORObfuscation(blob,length-2,opts,o);return o}function parseread(l){return function(blob,length){blob.l+=l;return}}function parseread1(blob,length){blob.l+=1;return}function parse_ColRelU(blob,length){var c=blob.read_shift(2);return[c&16383,c>>14&1,c>>15&1]}function parse_RgceArea(blob,length){var r=blob.read_shift(2),R=blob.read_shift(2);var c=parse_ColRelU(blob,2);var C=parse_ColRelU(blob,2);return{s:{r:r,c:c[0],cRel:c[1],rRel:c[2]},e:{r:R,c:C[0],cRel:C[1],rRel:C[2]}}}function parse_RgceAreaRel(blob,length){var r=blob.read_shift(2),R=blob.read_shift(2);var c=parse_ColRelU(blob,2);var C=parse_ColRelU(blob,2);return{s:{r:r,c:c[0],cRel:c[1],rRel:c[2]},e:{r:R,c:C[0],cRel:C[1],rRel:C[2]}}}function parse_RgceLoc(blob,length){var r=blob.read_shift(2);var c=parse_ColRelU(blob,2);return{r:r,c:c[0],cRel:c[1],rRel:c[2]}}function parse_RgceLocRel(blob,length){var r=blob.read_shift(2);var cl=blob.read_shift(2);var cRel=(cl&32768)>>15,rRel=(cl&16384)>>14;cl&=16383;if(cRel!==0)while(cl>=256)cl-=256;return{r:r,c:cl,cRel:cRel,rRel:rRel}}function parse_PtgArea(blob,length){var type=(blob[blob.l++]&96)>>5;var area=parse_RgceArea(blob,8);return[type,area]}function parse_PtgArea3d(blob,length){var type=(blob[blob.l++]&96)>>5;var ixti=blob.read_shift(2);var area=parse_RgceArea(blob,8);return[type,ixti,area]}function parse_PtgAreaErr(blob,length){var type=(blob[blob.l++]&96)>>5;blob.l+=8;return[type]}function parse_PtgAreaErr3d(blob,length){var type=(blob[blob.l++]&96)>>5;var ixti=blob.read_shift(2);blob.l+=8;return[type,ixti]}function parse_PtgAreaN(blob,length){var type=(blob[blob.l++]&96)>>5;var area=parse_RgceAreaRel(blob,8);return[type,area]}function parse_PtgArray(blob,length){var type=(blob[blob.l++]&96)>>5;blob.l+=7;return[type]}function parse_PtgAttrBaxcel(blob,length){var bitSemi=blob[blob.l+1]&1;var bitBaxcel=1;blob.l+=4;return[bitSemi,bitBaxcel]}function parse_PtgAttrChoose(blob,length){blob.l+=2;var offset=blob.read_shift(2);var o=[];for(var i=0;i<=offset;++i)o.push(blob.read_shift(2));return o}function parse_PtgAttrGoto(blob,length){var bitGoto=blob[blob.l+1]&255?1:0;blob.l+=2;return[bitGoto,blob.read_shift(2)]}function parse_PtgAttrIf(blob,length){var bitIf=blob[blob.l+1]&255?1:0;blob.l+=2;return[bitIf,blob.read_shift(2)]}function parse_PtgAttrSemi(blob,length){var bitSemi=blob[blob.l+1]&255?1:0;blob.l+=4;return[bitSemi]}function parse_PtgAttrSpaceType(blob,length){var type=blob.read_shift(1),cch=blob.read_shift(1);return[type,cch]}function parse_PtgAttrSpace(blob,length){blob.read_shift(2);return parse_PtgAttrSpaceType(blob,2)}function parse_PtgAttrSpaceSemi(blob,length){blob.read_shift(2);return parse_PtgAttrSpaceType(blob,2)}function parse_PtgRef(blob,length){var ptg=blob[blob.l]&31;var type=(blob[blob.l]&96)>>5;blob.l+=1;var loc=parse_RgceLoc(blob,4);return[type,loc]}function parse_PtgRefN(blob,length){var ptg=blob[blob.l]&31;var type=(blob[blob.l]&96)>>5;blob.l+=1;var loc=parse_RgceLocRel(blob,4);return[type,loc]}function parse_PtgRef3d(blob,length){var ptg=blob[blob.l]&31;var type=(blob[blob.l]&96)>>5;blob.l+=1;var ixti=blob.read_shift(2);var loc=parse_RgceLoc(blob,4);return[type,ixti,loc]}function parse_PtgFunc(blob,length){var ptg=blob[blob.l]&31;var type=(blob[blob.l]&96)>>5;blob.l+=1;var iftab=blob.read_shift(2);return[FtabArgc[iftab],Ftab[iftab]]}function parse_PtgFuncVar(blob,length){blob.l++;var cparams=blob.read_shift(1),tab=parsetab(blob);return[cparams,(tab[0]===0?Ftab:Cetab)[tab[1]]]}function parsetab(blob,length){return[blob[blob.l+1]>>7,blob.read_shift(2)&32767]}var parse_PtgAttrSum=parseread(4);var parse_PtgConcat=parseread1;function parse_PtgExp(blob,length){blob.l++;var row=blob.read_shift(2);var col=blob.read_shift(2);return[row,col]}function parse_PtgErr(blob,length){blob.l++;return BERR[blob.read_shift(1)]}function parse_PtgInt(blob,length){blob.l++;return blob.read_shift(2)}function parse_PtgBool(blob,length){blob.l++;return blob.read_shift(1)!==0}function parse_PtgNum(blob,length){blob.l++;return parse_Xnum(blob,8)}function parse_PtgStr(blob,length){blob.l++;return parse_ShortXLUnicodeString(blob)}function parse_SerAr(blob){var val=[];switch(val[0]=blob.read_shift(1)){case 4:val[1]=parsebool(blob,1)?"TRUE":"FALSE";blob.l+=7;break;case 16:val[1]=BERR[blob[blob.l]];blob.l+=8;break;case 0:blob.l+=8;break;case 1:val[1]=parse_Xnum(blob,8);break;case 2:val[1]=parse_XLUnicodeString(blob);break}return val}function parse_PtgExtraMem(blob,cce){var count=blob.read_shift(2);var out=[];for(var i=0;i!=count;++i)out.push(parse_Ref8U(blob,8));return out}function parse_PtgExtraArray(blob){var cols=1+blob.read_shift(1);var rows=1+blob.read_shift(2);for(var i=0,o=[];i!=rows&&(o[i]=[]);++i)for(var j=0;j!=cols;++j)o[i][j]=parse_SerAr(blob);return o}function parse_PtgName(blob,length){var type=blob.read_shift(1)>>>5&3;var nameindex=blob.read_shift(4);return[type,0,nameindex]}function parse_PtgNameX(blob,length){var type=blob.read_shift(1)>>>5&3;var ixti=blob.read_shift(2);var nameindex=blob.read_shift(4);return[type,ixti,nameindex]}function parse_PtgMemArea(blob,length){var type=blob.read_shift(1)>>>5&3;blob.l+=4;var cce=blob.read_shift(2);return[type,cce]}function parse_PtgMemFunc(blob,length){var type=blob.read_shift(1)>>>5&3;var cce=blob.read_shift(2);return[type,cce]}function parse_PtgRefErr(blob,length){var type=blob.read_shift(1)>>>5&3;blob.l+=4;return[type]}var parse_PtgAdd=parseread1;var parse_PtgDiv=parseread1;var parse_PtgEq=parseread1;var parse_PtgGe=parseread1;var parse_PtgGt=parseread1;var parse_PtgIsect=parseread1;var parse_PtgLe=parseread1;var parse_PtgLt=parseread1;var parse_PtgMissArg=parseread1;var parse_PtgMul=parseread1;var parse_PtgNe=parseread1;var parse_PtgParen=parseread1;var parse_PtgPercent=parseread1;var parse_PtgPower=parseread1;var parse_PtgRange=parseread1;var parse_PtgSub=parseread1;var parse_PtgUminus=parseread1;var parse_PtgUnion=parseread1;var parse_PtgUplus=parseread1;var parse_PtgMemErr=parsenoop;var parse_PtgMemNoMem=parsenoop;var parse_PtgRefErr3d=parsenoop;var parse_PtgTbl=parsenoop;var PtgTypes={1:{n:"PtgExp",f:parse_PtgExp},2:{n:"PtgTbl",f:parse_PtgTbl},3:{n:"PtgAdd",f:parse_PtgAdd},4:{n:"PtgSub",f:parse_PtgSub},5:{n:"PtgMul",f:parse_PtgMul},6:{n:"PtgDiv",f:parse_PtgDiv},7:{n:"PtgPower",f:parse_PtgPower},8:{n:"PtgConcat",f:parse_PtgConcat},9:{n:"PtgLt",f:parse_PtgLt},10:{n:"PtgLe",f:parse_PtgLe},11:{n:"PtgEq",f:parse_PtgEq},12:{n:"PtgGe",f:parse_PtgGe},13:{n:"PtgGt",f:parse_PtgGt},14:{n:"PtgNe",f:parse_PtgNe},15:{n:"PtgIsect",f:parse_PtgIsect},16:{n:"PtgUnion",f:parse_PtgUnion},17:{n:"PtgRange",f:parse_PtgRange},18:{n:"PtgUplus",f:parse_PtgUplus},19:{n:"PtgUminus",f:parse_PtgUminus},20:{n:"PtgPercent",f:parse_PtgPercent},21:{n:"PtgParen",f:parse_PtgParen},22:{n:"PtgMissArg",f:parse_PtgMissArg},23:{n:"PtgStr",f:parse_PtgStr},28:{n:"PtgErr",f:parse_PtgErr},29:{n:"PtgBool",f:parse_PtgBool},30:{n:"PtgInt",f:parse_PtgInt},31:{n:"PtgNum",f:parse_PtgNum},32:{n:"PtgArray",f:parse_PtgArray},33:{n:"PtgFunc",f:parse_PtgFunc},34:{n:"PtgFuncVar",f:parse_PtgFuncVar},35:{n:"PtgName",f:parse_PtgName},36:{n:"PtgRef",f:parse_PtgRef},37:{n:"PtgArea",f:parse_PtgArea},38:{n:"PtgMemArea",f:parse_PtgMemArea},39:{n:"PtgMemErr",f:parse_PtgMemErr},40:{n:"PtgMemNoMem",f:parse_PtgMemNoMem},41:{n:"PtgMemFunc",f:parse_PtgMemFunc},42:{n:"PtgRefErr",f:parse_PtgRefErr},43:{n:"PtgAreaErr",f:parse_PtgAreaErr},44:{n:"PtgRefN",f:parse_PtgRefN},45:{n:"PtgAreaN",f:parse_PtgAreaN},57:{n:"PtgNameX",f:parse_PtgNameX},58:{n:"PtgRef3d",f:parse_PtgRef3d},59:{n:"PtgArea3d",f:parse_PtgArea3d},60:{n:"PtgRefErr3d",f:parse_PtgRefErr3d},61:{n:"PtgAreaErr3d",f:parse_PtgAreaErr3d},255:{}};var PtgDupes={64:32,96:32,65:33,97:33,66:34,98:34,67:35,99:35,68:36,100:36,69:37,101:37,70:38,102:38,71:39,103:39,72:40,104:40,73:41,105:41,74:42,106:42,75:43,107:43,76:44,108:44,77:45,109:45,89:57,121:57,90:58,122:58,91:59,123:59,92:60,124:60,93:61,125:61};(function(){for(var y in PtgDupes)PtgTypes[y]=PtgTypes[PtgDupes[y]]})();var Ptg18={};var Ptg19={1:{n:"PtgAttrSemi",f:parse_PtgAttrSemi},2:{n:"PtgAttrIf",f:parse_PtgAttrIf},4:{n:"PtgAttrChoose",f:parse_PtgAttrChoose},8:{n:"PtgAttrGoto",f:parse_PtgAttrGoto},16:{n:"PtgAttrSum",f:parse_PtgAttrSum},32:{n:"PtgAttrBaxcel",f:parse_PtgAttrBaxcel},64:{n:"PtgAttrSpace",f:parse_PtgAttrSpace},65:{n:"PtgAttrSpaceSemi",f:parse_PtgAttrSpaceSemi},255:{}};var rcregex=/(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;var rcbase;function rcfunc($$,$1,$2,$3,$4,$5){var R=$3.length>0?parseInt($3,10)|0:0,C=$5.length>0?parseInt($5,10)|0:0;if(C<0&&$4.length===0)C=0;if($4.length>0)C+=rcbase.c;if($2.length>0)R+=rcbase.r;return $1+encode_col(C)+encode_row(R)}function rc_to_a1(fstr,base){rcbase=base;return fstr.replace(rcregex,rcfunc)}function parse_Formula(blob,length,opts){var cell=parse_Cell(blob,6);var val=parse_FormulaValue(blob,8);var flags=blob.read_shift(1);blob.read_shift(1);var chn=blob.read_shift(4);var cbf="";if(opts.biff===5)blob.l+=length-20;else cbf=parse_CellParsedFormula(blob,length-20,opts);return{cell:cell,val:val[0],formula:cbf,shared:flags>>3&1,tt:val[1]}}function parse_FormulaValue(blob){var b;if(__readUInt16LE(blob,blob.l+6)!==65535)return[parse_Xnum(blob),"n"];switch(blob[blob.l]){case 0:blob.l+=8;return["String","s"];case 1:b=blob[blob.l+2]===1;blob.l+=8;return[b,"b"];case 2:b=BERR[blob[blob.l+2]];blob.l+=8;return[b,"e"];case 3:blob.l+=8;return["","s"]}}function parse_RgbExtra(blob,length,rgce,opts){if(opts.biff<8)return parsenoop(blob,length);var target=blob.l+length;var o=[];for(var i=0;i!==rgce.length;++i){switch(rgce[i][0]){case"PtgArray":rgce[i][1]=parse_PtgExtraArray(blob);o.push(rgce[i][1]);break;case"PtgMemArea":rgce[i][2]=parse_PtgExtraMem(blob,rgce[i][1]);o.push(rgce[i][2]);break;default:break}}length=target-blob.l;if(length!==0)o.push(parsenoop(blob,length));return o}function parse_NameParsedFormula(blob,length,opts,cce){var target=blob.l+length;var rgce=parse_Rgce(blob,cce);var rgcb;if(target!==blob.l)rgcb=parse_RgbExtra(blob,target-blob.l,rgce,opts);return[rgce,rgcb]}function parse_CellParsedFormula(blob,length,opts){var target=blob.l+length;var rgcb,cce=blob.read_shift(2);if(cce==65535)return[[],parsenoop(blob,length-2)];var rgce=parse_Rgce(blob,cce);if(length!==cce+2)rgcb=parse_RgbExtra(blob,length-cce-2,rgce,opts);return[rgce,rgcb]}function parse_SharedParsedFormula(blob,length,opts){var target=blob.l+length;var rgcb,cce=blob.read_shift(2);var rgce=parse_Rgce(blob,cce);if(cce==65535)return[[],parsenoop(blob,length-2)];if(length!==cce+2)rgcb=parse_RgbExtra(blob,target-cce-2,rgce,opts);return[rgce,rgcb]}function parse_ArrayParsedFormula(blob,length,opts,ref){var target=blob.l+length;var rgcb,cce=blob.read_shift(2);if(cce==65535)return[[],parsenoop(blob,length-2)];var rgce=parse_Rgce(blob,cce);if(length!==cce+2)rgcb=parse_RgbExtra(blob,target-cce-2,rgce,opts);return[rgce,rgcb]}function parse_Rgce(blob,length){var target=blob.l+length;var R,id,ptgs=[];while(target!=blob.l){length=target-blob.l;id=blob[blob.l];R=PtgTypes[id];if(id===24||id===25){id=blob[blob.l+1];R=(id===24?Ptg18:Ptg19)[id]}if(!R||!R.f){ptgs.push(parsenoop(blob,length))}else{ptgs.push([R.n,R.f(blob,length)])}}return ptgs}function mapper(x){return x.map(function f2(y){return y[1]}).join(",")}function stringify_formula(formula,range,cell,supbooks,opts){if(opts!==undefined&&opts.biff===5)return"BIFF5??";var _range=range!==undefined?range:{s:{c:0,r:0}};var stack=[],e1,e2,type,c,ixti,nameidx,r;if(!formula[0]||!formula[0][0])return"";for(var ff=0,fflen=formula[0].length;ff<fflen;++ff){var f=formula[0][ff];switch(f[0]){case"PtgUminus":stack.push("-"+stack.pop());break;case"PtgUplus":stack.push("+"+stack.pop());break;case"PtgPercent":stack.push(stack.pop()+"%");break;case"PtgAdd":e1=stack.pop();e2=stack.pop();stack.push(e2+"+"+e1);break;case"PtgSub":e1=stack.pop();e2=stack.pop();stack.push(e2+"-"+e1);break;case"PtgMul":e1=stack.pop();e2=stack.pop();stack.push(e2+"*"+e1);break;case"PtgDiv":e1=stack.pop();e2=stack.pop();stack.push(e2+"/"+e1);break;case"PtgPower":e1=stack.pop();e2=stack.pop();stack.push(e2+"^"+e1);break;case"PtgConcat":e1=stack.pop();e2=stack.pop();stack.push(e2+"&"+e1);break;case"PtgLt":e1=stack.pop();e2=stack.pop();stack.push(e2+"<"+e1);break;case"PtgLe":e1=stack.pop();e2=stack.pop();stack.push(e2+"<="+e1);break;case"PtgEq":e1=stack.pop();e2=stack.pop();stack.push(e2+"="+e1);break;case"PtgGe":e1=stack.pop();e2=stack.pop();stack.push(e2+">="+e1);break;case"PtgGt":e1=stack.pop();e2=stack.pop();stack.push(e2+">"+e1);break;case"PtgNe":e1=stack.pop();e2=stack.pop();stack.push(e2+"<>"+e1);break;case"PtgIsect":e1=stack.pop();e2=stack.pop();stack.push(e2+" "+e1);break;case"PtgUnion":e1=stack.pop();e2=stack.pop();stack.push(e2+","+e1);break;case"PtgRange":break;case"PtgAttrChoose":break;case"PtgAttrGoto":break;case"PtgAttrIf":break;case"PtgRef":type=f[1][0];c=shift_cell(decode_cell(encode_cell(f[1][1])),_range);stack.push(encode_cell(c));break;case"PtgRefN":type=f[1][0];c=shift_cell(decode_cell(encode_cell(f[1][1])),cell);stack.push(encode_cell(c));break;case"PtgRef3d":type=f[1][0];ixti=f[1][1];c=shift_cell(f[1][2],_range);stack.push(supbooks[1][ixti+1]+"!"+encode_cell(c));break;case"PtgFunc":case"PtgFuncVar":var argc=f[1][0],func=f[1][1];if(!argc)argc=0;var args=stack.slice(-argc);stack.length-=argc;if(func==="User")func=args.shift();stack.push(func+"("+args.join(",")+")");break;case"PtgBool":stack.push(f[1]?"TRUE":"FALSE");break;case"PtgInt":stack.push(f[1]);break;case"PtgNum":stack.push(String(f[1]));break;case"PtgStr":stack.push('"'+f[1]+'"');break;case"PtgErr":stack.push(f[1]);break;case"PtgArea":type=f[1][0];r=shift_range(f[1][1],_range);stack.push(encode_range(r));break;case"PtgArea3d":type=f[1][0];ixti=f[1][1];r=f[1][2];stack.push(supbooks[1][ixti+1]+"!"+encode_range(r));break;case"PtgAttrSum":stack.push("SUM("+stack.pop()+")");break;case"PtgAttrSemi":break;case"PtgName":nameidx=f[1][2];var lbl=supbooks[0][nameidx];var name=lbl.Name;if(name in XLSXFutureFunctions)name=XLSXFutureFunctions[name];stack.push(name);break;case"PtgNameX":var bookidx=f[1][1];nameidx=f[1][2];var externbook;if(supbooks[bookidx+1])externbook=supbooks[bookidx+1][nameidx];else if(supbooks[bookidx-1])externbook=supbooks[bookidx-1][nameidx];if(!externbook)externbook={body:"??NAMEX??"};stack.push(externbook.body);break;case"PtgParen":stack.push("("+stack.pop()+")");break;case"PtgRefErr":stack.push("#REF!");break;case"PtgExp":c={c:f[1][1],r:f[1][0]};var q={c:cell.c,r:cell.r};if(supbooks.sharedf[encode_cell(c)]){var parsedf=supbooks.sharedf[encode_cell(c)];stack.push(stringify_formula(parsedf,_range,q,supbooks,opts))}else{var fnd=false;for(e1=0;e1!=supbooks.arrayf.length;++e1){e2=supbooks.arrayf[e1];if(c.c<e2[0].s.c||c.c>e2[0].e.c)continue;if(c.r<e2[0].s.r||c.r>e2[0].e.r)continue;stack.push(stringify_formula(e2[1],_range,q,supbooks,opts))}if(!fnd)stack.push(f[1])}break;case"PtgArray":stack.push("{"+f[1].map(mapper).join(";")+"}");break;case"PtgMemArea":break;case"PtgAttrSpace":break;case"PtgTbl":break;case"PtgMemErr":break;case"PtgMissArg":stack.push("");break;case"PtgAreaErr":break;case"PtgAreaN":stack.push("");break;case"PtgRefErr3d":break;case"PtgMemFunc":break;default:throw"Unrecognized Formula Token: "+f}}return stack[0]}var PtgDataType={1:"REFERENCE",2:"VALUE",3:"ARRAY"};var BERR={0:"#NULL!",7:"#DIV/0!",15:"#VALUE!",23:"#REF!",29:"#NAME?",36:"#NUM!",42:"#N/A",43:"#GETTING_DATA",255:"#WTF?"};var Cetab={0:"BEEP",1:"OPEN",2:"OPEN.LINKS",3:"CLOSE.ALL",4:"SAVE",5:"SAVE.AS",6:"FILE.DELETE",7:"PAGE.SETUP",8:"PRINT",9:"PRINTER.SETUP",10:"QUIT",11:"NEW.WINDOW",12:"ARRANGE.ALL",13:"WINDOW.SIZE",14:"WINDOW.MOVE",15:"FULL",16:"CLOSE",17:"RUN",22:"SET.PRINT.AREA",23:"SET.PRINT.TITLES",24:"SET.PAGE.BREAK",25:"REMOVE.PAGE.BREAK",26:"FONT",27:"DISPLAY",28:"PROTECT.DOCUMENT",29:"PRECISION",30:"A1.R1C1",31:"CALCULATE.NOW",32:"CALCULATION",34:"DATA.FIND",35:"EXTRACT",36:"DATA.DELETE",37:"SET.DATABASE",38:"SET.CRITERIA",39:"SORT",40:"DATA.SERIES",41:"TABLE",42:"FORMAT.NUMBER",43:"ALIGNMENT",44:"STYLE",45:"BORDER",46:"CELL.PROTECTION",47:"COLUMN.WIDTH",48:"UNDO",49:"CUT",50:"COPY",51:"PASTE",52:"CLEAR",53:"PASTE.SPECIAL",54:"EDIT.DELETE",55:"INSERT",56:"FILL.RIGHT",57:"FILL.DOWN",61:"DEFINE.NAME",62:"CREATE.NAMES",63:"FORMULA.GOTO",64:"FORMULA.FIND",65:"SELECT.LAST.CELL",66:"SHOW.ACTIVE.CELL",67:"GALLERY.AREA",68:"GALLERY.BAR",69:"GALLERY.COLUMN",70:"GALLERY.LINE",71:"GALLERY.PIE",72:"GALLERY.SCATTER",73:"COMBINATION",74:"PREFERRED",75:"ADD.OVERLAY",76:"GRIDLINES",77:"SET.PREFERRED",78:"AXES",79:"LEGEND",80:"ATTACH.TEXT",81:"ADD.ARROW",82:"SELECT.CHART",83:"SELECT.PLOT.AREA",84:"PATTERNS",85:"MAIN.CHART",86:"OVERLAY",87:"SCALE",88:"FORMAT.LEGEND",89:"FORMAT.TEXT",90:"EDIT.REPEAT",91:"PARSE",92:"JUSTIFY",93:"HIDE",94:"UNHIDE",95:"WORKSPACE",96:"FORMULA",97:"FORMULA.FILL",98:"FORMULA.ARRAY",99:"DATA.FIND.NEXT",100:"DATA.FIND.PREV",101:"FORMULA.FIND.NEXT",102:"FORMULA.FIND.PREV",103:"ACTIVATE",104:"ACTIVATE.NEXT",105:"ACTIVATE.PREV",106:"UNLOCKED.NEXT",107:"UNLOCKED.PREV",108:"COPY.PICTURE",109:"SELECT",110:"DELETE.NAME",111:"DELETE.FORMAT",112:"VLINE",113:"HLINE",114:"VPAGE",115:"HPAGE",116:"VSCROLL",117:"HSCROLL",118:"ALERT",119:"NEW",120:"CANCEL.COPY",121:"SHOW.CLIPBOARD",122:"MESSAGE",124:"PASTE.LINK",125:"APP.ACTIVATE",126:"DELETE.ARROW",127:"ROW.HEIGHT",128:"FORMAT.MOVE",129:"FORMAT.SIZE",130:"FORMULA.REPLACE",131:"SEND.KEYS",132:"SELECT.SPECIAL",133:"APPLY.NAMES",134:"REPLACE.FONT",135:"FREEZE.PANES",136:"SHOW.INFO",137:"SPLIT",138:"ON.WINDOW",139:"ON.DATA",140:"DISABLE.INPUT",142:"OUTLINE",143:"LIST.NAMES",144:"FILE.CLOSE",145:"SAVE.WORKBOOK",146:"DATA.FORM",147:"COPY.CHART",148:"ON.TIME",149:"WAIT",150:"FORMAT.FONT",151:"FILL.UP",152:"FILL.LEFT",153:"DELETE.OVERLAY",155:"SHORT.MENUS",159:"SET.UPDATE.STATUS",161:"COLOR.PALETTE",162:"DELETE.STYLE",163:"WINDOW.RESTORE",164:"WINDOW.MAXIMIZE",166:"CHANGE.LINK",167:"CALCULATE.DOCUMENT",168:"ON.KEY",169:"APP.RESTORE",170:"APP.MOVE",171:"APP.SIZE",172:"APP.MINIMIZE",173:"APP.MAXIMIZE",174:"BRING.TO.FRONT",175:"SEND.TO.BACK",185:"MAIN.CHART.TYPE",186:"OVERLAY.CHART.TYPE",187:"SELECT.END",188:"OPEN.MAIL",189:"SEND.MAIL",190:"STANDARD.FONT",191:"CONSOLIDATE",192:"SORT.SPECIAL",193:"GALLERY.3D.AREA",194:"GALLERY.3D.COLUMN",195:"GALLERY.3D.LINE",196:"GALLERY.3D.PIE",197:"VIEW.3D",198:"GOAL.SEEK",199:"WORKGROUP",200:"FILL.GROUP",201:"UPDATE.LINK",202:"PROMOTE",203:"DEMOTE",204:"SHOW.DETAIL",206:"UNGROUP",207:"OBJECT.PROPERTIES",208:"SAVE.NEW.OBJECT",209:"SHARE",210:"SHARE.NAME",211:"DUPLICATE",212:"APPLY.STYLE",213:"ASSIGN.TO.OBJECT",214:"OBJECT.PROTECTION",215:"HIDE.OBJECT",216:"SET.EXTRACT",217:"CREATE.PUBLISHER",218:"SUBSCRIBE.TO",219:"ATTRIBUTES",220:"SHOW.TOOLBAR",222:"PRINT.PREVIEW",223:"EDIT.COLOR",224:"SHOW.LEVELS",225:"FORMAT.MAIN",226:"FORMAT.OVERLAY",227:"ON.RECALC",228:"EDIT.SERIES",229:"DEFINE.STYLE",240:"LINE.PRINT",243:"ENTER.DATA",249:"GALLERY.RADAR",250:"MERGE.STYLES",251:"EDITION.OPTIONS",252:"PASTE.PICTURE",253:"PASTE.PICTURE.LINK",254:"SPELLING",256:"ZOOM",259:"INSERT.OBJECT",260:"WINDOW.MINIMIZE",265:"SOUND.NOTE",266:"SOUND.PLAY",267:"FORMAT.SHAPE",268:"EXTEND.POLYGON",269:"FORMAT.AUTO",272:"GALLERY.3D.BAR",273:"GALLERY.3D.SURFACE",274:"FILL.AUTO",276:"CUSTOMIZE.TOOLBAR",277:"ADD.TOOL",278:"EDIT.OBJECT",279:"ON.DOUBLECLICK",280:"ON.ENTRY",281:"WORKBOOK.ADD",282:"WORKBOOK.MOVE",283:"WORKBOOK.COPY",284:"WORKBOOK.OPTIONS",285:"SAVE.WORKSPACE",288:"CHART.WIZARD",289:"DELETE.TOOL",290:"MOVE.TOOL",291:"WORKBOOK.SELECT",292:"WORKBOOK.ACTIVATE",293:"ASSIGN.TO.TOOL",295:"COPY.TOOL",296:"RESET.TOOL",297:"CONSTRAIN.NUMERIC",298:"PASTE.TOOL",302:"WORKBOOK.NEW",305:"SCENARIO.CELLS",306:"SCENARIO.DELETE",307:"SCENARIO.ADD",308:"SCENARIO.EDIT",309:"SCENARIO.SHOW",310:"SCENARIO.SHOW.NEXT",311:"SCENARIO.SUMMARY",312:"PIVOT.TABLE.WIZARD",313:"PIVOT.FIELD.PROPERTIES",314:"PIVOT.FIELD",315:"PIVOT.ITEM",316:"PIVOT.ADD.FIELDS",318:"OPTIONS.CALCULATION",319:"OPTIONS.EDIT",320:"OPTIONS.VIEW",321:"ADDIN.MANAGER",322:"MENU.EDITOR",323:"ATTACH.TOOLBARS",324:"VBAActivate",325:"OPTIONS.CHART",328:"VBA.INSERT.FILE",330:"VBA.PROCEDURE.DEFINITION",336:"ROUTING.SLIP",338:"ROUTE.DOCUMENT",339:"MAIL.LOGON",342:"INSERT.PICTURE",343:"EDIT.TOOL",344:"GALLERY.DOUGHNUT",350:"CHART.TREND",352:"PIVOT.ITEM.PROPERTIES",354:"WORKBOOK.INSERT",355:"OPTIONS.TRANSITION",356:"OPTIONS.GENERAL",370:"FILTER.ADVANCED",373:"MAIL.ADD.MAILER",374:"MAIL.DELETE.MAILER",375:"MAIL.REPLY",376:"MAIL.REPLY.ALL",377:"MAIL.FORWARD",378:"MAIL.NEXT.LETTER",379:"DATA.LABEL",380:"INSERT.TITLE",381:"FONT.PROPERTIES",382:"MACRO.OPTIONS",383:"WORKBOOK.HIDE",384:"WORKBOOK.UNHIDE",385:"WORKBOOK.DELETE",386:"WORKBOOK.NAME",388:"GALLERY.CUSTOM",390:"ADD.CHART.AUTOFORMAT",391:"DELETE.CHART.AUTOFORMAT",392:"CHART.ADD.DATA",393:"AUTO.OUTLINE",394:"TAB.ORDER",395:"SHOW.DIALOG",396:"SELECT.ALL",397:"UNGROUP.SHEETS",398:"SUBTOTAL.CREATE",399:"SUBTOTAL.REMOVE",400:"RENAME.OBJECT",412:"WORKBOOK.SCROLL",413:"WORKBOOK.NEXT",414:"WORKBOOK.PREV",415:"WORKBOOK.TAB.SPLIT",416:"FULL.SCREEN",417:"WORKBOOK.PROTECT",420:"SCROLLBAR.PROPERTIES",421:"PIVOT.SHOW.PAGES",422:"TEXT.TO.COLUMNS",423:"FORMAT.CHARTTYPE",424:"LINK.FORMAT",425:"TRACER.DISPLAY",430:"TRACER.NAVIGATE",431:"TRACER.CLEAR",432:"TRACER.ERROR",433:"PIVOT.FIELD.GROUP",434:"PIVOT.FIELD.UNGROUP",435:"CHECKBOX.PROPERTIES",436:"LABEL.PROPERTIES",437:"LISTBOX.PROPERTIES",438:"EDITBOX.PROPERTIES",439:"PIVOT.REFRESH",440:"LINK.COMBO",441:"OPEN.TEXT",442:"HIDE.DIALOG",443:"SET.DIALOG.FOCUS",444:"ENABLE.OBJECT",445:"PUSHBUTTON.PROPERTIES",446:"SET.DIALOG.DEFAULT",447:"FILTER",448:"FILTER.SHOW.ALL",449:"CLEAR.OUTLINE",450:"FUNCTION.WIZARD",451:"ADD.LIST.ITEM",452:"SET.LIST.ITEM",453:"REMOVE.LIST.ITEM",454:"SELECT.LIST.ITEM",455:"SET.CONTROL.VALUE",456:"SAVE.COPY.AS",458:"OPTIONS.LISTS.ADD",459:"OPTIONS.LISTS.DELETE",460:"SERIES.AXES",461:"SERIES.X",462:"SERIES.Y",463:"ERRORBAR.X",464:"ERRORBAR.Y",465:"FORMAT.CHART",466:"SERIES.ORDER",467:"MAIL.LOGOFF",468:"CLEAR.ROUTING.SLIP",469:"APP.ACTIVATE.MICROSOFT",470:"MAIL.EDIT.MAILER",471:"ON.SHEET",472:"STANDARD.WIDTH",473:"SCENARIO.MERGE",474:"SUMMARY.INFO",475:"FIND.FILE",476:"ACTIVE.CELL.FONT",477:"ENABLE.TIPWIZARD",478:"VBA.MAKE.ADDIN",480:"INSERTDATATABLE",481:"WORKGROUP.OPTIONS",482:"MAIL.SEND.MAILER",485:"AUTOCORRECT",489:"POST.DOCUMENT",491:"PICKLIST",493:"VIEW.SHOW",494:"VIEW.DEFINE",495:"VIEW.DELETE",509:"SHEET.BACKGROUND",510:"INSERT.MAP.OBJECT",511:"OPTIONS.MENONO",517:"MSOCHECKS",518:"NORMAL",519:"LAYOUT",520:"RM.PRINT.AREA",521:"CLEAR.PRINT.AREA",522:"ADD.PRINT.AREA",523:"MOVE.BRK",545:"HIDECURR.NOTE",546:"HIDEALL.NOTES",547:"DELETE.NOTE",548:"TRAVERSE.NOTES",549:"ACTIVATE.NOTES",620:"PROTECT.REVISIONS",621:"UNPROTECT.REVISIONS",647:"OPTIONS.ME",653:"WEB.PUBLISH",667:"NEWWEBQUERY",673:"PIVOT.TABLE.CHART",753:"OPTIONS.SAVE",755:"OPTIONS.SPELL",808:"HIDEALL.INKANNOTS"};
18561 var Ftab={0:"COUNT",1:"IF",2:"ISNA",3:"ISERROR",4:"SUM",5:"AVERAGE",6:"MIN",7:"MAX",8:"ROW",9:"COLUMN",10:"NA",11:"NPV",12:"STDEV",13:"DOLLAR",14:"FIXED",15:"SIN",16:"COS",17:"TAN",18:"ATAN",19:"PI",20:"SQRT",21:"EXP",22:"LN",23:"LOG10",24:"ABS",25:"INT",26:"SIGN",27:"ROUND",28:"LOOKUP",29:"INDEX",30:"REPT",31:"MID",32:"LEN",33:"VALUE",34:"TRUE",35:"FALSE",36:"AND",37:"OR",38:"NOT",39:"MOD",40:"DCOUNT",41:"DSUM",42:"DAVERAGE",43:"DMIN",44:"DMAX",45:"DSTDEV",46:"VAR",47:"DVAR",48:"TEXT",49:"LINEST",50:"TREND",51:"LOGEST",52:"GROWTH",53:"GOTO",54:"HALT",55:"RETURN",56:"PV",57:"FV",58:"NPER",59:"PMT",60:"RATE",61:"MIRR",62:"IRR",63:"RAND",64:"MATCH",65:"DATE",66:"TIME",67:"DAY",68:"MONTH",69:"YEAR",70:"WEEKDAY",71:"HOUR",72:"MINUTE",73:"SECOND",74:"NOW",75:"AREAS",76:"ROWS",77:"COLUMNS",78:"OFFSET",79:"ABSREF",80:"RELREF",81:"ARGUMENT",82:"SEARCH",83:"TRANSPOSE",84:"ERROR",85:"STEP",86:"TYPE",87:"ECHO",88:"SET.NAME",89:"CALLER",90:"DEREF",91:"WINDOWS",92:"SERIES",93:"DOCUMENTS",94:"ACTIVE.CELL",95:"SELECTION",96:"RESULT",97:"ATAN2",98:"ASIN",99:"ACOS",100:"CHOOSE",101:"HLOOKUP",102:"VLOOKUP",103:"LINKS",104:"INPUT",105:"ISREF",106:"GET.FORMULA",107:"GET.NAME",108:"SET.VALUE",109:"LOG",110:"EXEC",111:"CHAR",112:"LOWER",113:"UPPER",114:"PROPER",115:"LEFT",116:"RIGHT",117:"EXACT",118:"TRIM",119:"REPLACE",120:"SUBSTITUTE",121:"CODE",122:"NAMES",123:"DIRECTORY",124:"FIND",125:"CELL",126:"ISERR",127:"ISTEXT",128:"ISNUMBER",129:"ISBLANK",130:"T",131:"N",132:"FOPEN",133:"FCLOSE",134:"FSIZE",135:"FREADLN",136:"FREAD",137:"FWRITELN",138:"FWRITE",139:"FPOS",140:"DATEVALUE",141:"TIMEVALUE",142:"SLN",143:"SYD",144:"DDB",145:"GET.DEF",146:"REFTEXT",147:"TEXTREF",148:"INDIRECT",149:"REGISTER",150:"CALL",151:"ADD.BAR",152:"ADD.MENU",153:"ADD.COMMAND",154:"ENABLE.COMMAND",155:"CHECK.COMMAND",156:"RENAME.COMMAND",157:"SHOW.BAR",158:"DELETE.MENU",159:"DELETE.COMMAND",160:"GET.CHART.ITEM",161:"DIALOG.BOX",162:"CLEAN",163:"MDETERM",164:"MINVERSE",165:"MMULT",166:"FILES",167:"IPMT",168:"PPMT",169:"COUNTA",170:"CANCEL.KEY",171:"FOR",172:"WHILE",173:"BREAK",174:"NEXT",175:"INITIATE",176:"REQUEST",177:"POKE",178:"EXECUTE",179:"TERMINATE",180:"RESTART",181:"HELP",182:"GET.BAR",183:"PRODUCT",184:"FACT",185:"GET.CELL",186:"GET.WORKSPACE",187:"GET.WINDOW",188:"GET.DOCUMENT",189:"DPRODUCT",190:"ISNONTEXT",191:"GET.NOTE",192:"NOTE",193:"STDEVP",194:"VARP",195:"DSTDEVP",196:"DVARP",197:"TRUNC",198:"ISLOGICAL",199:"DCOUNTA",200:"DELETE.BAR",201:"UNREGISTER",204:"USDOLLAR",205:"FINDB",206:"SEARCHB",207:"REPLACEB",208:"LEFTB",209:"RIGHTB",210:"MIDB",211:"LENB",212:"ROUNDUP",213:"ROUNDDOWN",214:"ASC",215:"DBCS",216:"RANK",219:"ADDRESS",220:"DAYS360",221:"TODAY",222:"VDB",223:"ELSE",224:"ELSE.IF",225:"END.IF",226:"FOR.CELL",227:"MEDIAN",228:"SUMPRODUCT",229:"SINH",230:"COSH",231:"TANH",232:"ASINH",233:"ACOSH",234:"ATANH",235:"DGET",236:"CREATE.OBJECT",237:"VOLATILE",238:"LAST.ERROR",239:"CUSTOM.UNDO",240:"CUSTOM.REPEAT",241:"FORMULA.CONVERT",242:"GET.LINK.INFO",243:"TEXT.BOX",244:"INFO",245:"GROUP",246:"GET.OBJECT",247:"DB",248:"PAUSE",251:"RESUME",252:"FREQUENCY",253:"ADD.TOOLBAR",254:"DELETE.TOOLBAR",255:"User",256:"RESET.TOOLBAR",257:"EVALUATE",258:"GET.TOOLBAR",259:"GET.TOOL",260:"SPELLING.CHECK",261:"ERROR.TYPE",262:"APP.TITLE",263:"WINDOW.TITLE",264:"SAVE.TOOLBAR",265:"ENABLE.TOOL",266:"PRESS.TOOL",267:"REGISTER.ID",268:"GET.WORKBOOK",269:"AVEDEV",270:"BETADIST",271:"GAMMALN",272:"BETAINV",273:"BINOMDIST",274:"CHIDIST",275:"CHIINV",276:"COMBIN",277:"CONFIDENCE",278:"CRITBINOM",279:"EVEN",280:"EXPONDIST",281:"FDIST",282:"FINV",283:"FISHER",284:"FISHERINV",285:"FLOOR",286:"GAMMADIST",287:"GAMMAINV",288:"CEILING",289:"HYPGEOMDIST",290:"LOGNORMDIST",291:"LOGINV",292:"NEGBINOMDIST",293:"NORMDIST",294:"NORMSDIST",295:"NORMINV",296:"NORMSINV",297:"STANDARDIZE",298:"ODD",299:"PERMUT",300:"POISSON",301:"TDIST",302:"WEIBULL",303:"SUMXMY2",304:"SUMX2MY2",305:"SUMX2PY2",306:"CHITEST",307:"CORREL",308:"COVAR",309:"FORECAST",310:"FTEST",311:"INTERCEPT",312:"PEARSON",313:"RSQ",314:"STEYX",315:"SLOPE",316:"TTEST",317:"PROB",318:"DEVSQ",319:"GEOMEAN",320:"HARMEAN",321:"SUMSQ",322:"KURT",323:"SKEW",324:"ZTEST",325:"LARGE",326:"SMALL",327:"QUARTILE",328:"PERCENTILE",329:"PERCENTRANK",330:"MODE",331:"TRIMMEAN",332:"TINV",334:"MOVIE.COMMAND",335:"GET.MOVIE",336:"CONCATENATE",337:"POWER",338:"PIVOT.ADD.DATA",339:"GET.PIVOT.TABLE",340:"GET.PIVOT.FIELD",341:"GET.PIVOT.ITEM",342:"RADIANS",343:"DEGREES",344:"SUBTOTAL",345:"SUMIF",346:"COUNTIF",347:"COUNTBLANK",348:"SCENARIO.GET",349:"OPTIONS.LISTS.GET",350:"ISPMT",351:"DATEDIF",352:"DATESTRING",353:"NUMBERSTRING",354:"ROMAN",355:"OPEN.DIALOG",356:"SAVE.DIALOG",357:"VIEW.GET",358:"GETPIVOTDATA",359:"HYPERLINK",360:"PHONETIC",361:"AVERAGEA",362:"MAXA",363:"MINA",364:"STDEVPA",365:"VARPA",366:"STDEVA",367:"VARA",368:"BAHTTEXT",369:"THAIDAYOFWEEK",370:"THAIDIGIT",371:"THAIMONTHOFYEAR",372:"THAINUMSOUND",373:"THAINUMSTRING",374:"THAISTRINGLENGTH",375:"ISTHAIDIGIT",376:"ROUNDBAHTDOWN",377:"ROUNDBAHTUP",378:"THAIYEAR",379:"RTD"};var FtabArgc={2:1,3:1,15:1,16:1,17:1,18:1,20:1,21:1,22:1,23:1,24:1,25:1,26:1,27:2,30:2,31:3,32:1,33:1,38:1,39:2,40:3,41:3,42:3,43:3,44:3,45:3,47:3,48:2,53:1,61:3,65:3,66:3,67:1,68:1,69:1,71:1,72:1,73:1,75:1,76:1,77:1,79:2,80:2,83:1,86:1,90:1,97:2,98:1,99:1,105:1,111:1,112:1,113:1,114:1,117:2,118:1,119:4,121:1,126:1,127:1,128:1,129:1,130:1,131:1,133:1,134:1,135:1,136:2,137:2,138:2,140:1,141:1,142:3,143:4,162:1,163:1,164:1,165:2,172:1,175:2,176:2,177:3,178:2,179:1,184:1,189:3,190:1,195:3,196:3,198:1,199:3,201:1,207:4,210:3,211:1,212:2,213:2,214:1,215:1,229:1,230:1,231:1,232:1,233:1,234:1,235:3,244:1,252:2,257:1,261:1,271:1,273:4,274:2,275:2,276:2,277:3,278:3,279:1,280:3,281:3,282:3,283:1,284:1,285:2,286:4,287:3,288:2,289:4,290:3,291:3,292:3,293:4,294:1,295:3,296:1,297:3,298:1,299:2,300:3,301:3,302:4,303:2,304:2,305:2,306:2,307:2,308:2,309:3,310:2,311:2,312:2,313:2,314:2,315:2,316:4,325:2,326:2,327:2,328:2,331:2,332:2,337:2,342:1,343:1,346:2,347:1,350:4,351:3,352:1,353:2,360:1,368:1,369:1,370:1,371:1,372:1,373:1,374:1,375:1,376:1,377:1,378:1,65535:0};var XLSXFutureFunctions={"_xlfn.ACOT":"ACOT","_xlfn.ACOTH":"ACOTH","_xlfn.AGGREGATE":"AGGREGATE","_xlfn.ARABIC":"ARABIC","_xlfn.AVERAGEIF":"AVERAGEIF","_xlfn.AVERAGEIFS":"AVERAGEIFS","_xlfn.BASE":"BASE","_xlfn.BETA.DIST":"BETA.DIST","_xlfn.BETA.INV":"BETA.INV","_xlfn.BINOM.DIST":"BINOM.DIST","_xlfn.BINOM.DIST.RANGE":"BINOM.DIST.RANGE","_xlfn.BINOM.INV":"BINOM.INV","_xlfn.BITAND":"BITAND","_xlfn.BITLSHIFT":"BITLSHIFT","_xlfn.BITOR":"BITOR","_xlfn.BITRSHIFT":"BITRSHIFT","_xlfn.BITXOR":"BITXOR","_xlfn.CEILING.MATH":"CEILING.MATH","_xlfn.CEILING.PRECISE":"CEILING.PRECISE","_xlfn.CHISQ.DIST":"CHISQ.DIST","_xlfn.CHISQ.DIST.RT":"CHISQ.DIST.RT","_xlfn.CHISQ.INV":"CHISQ.INV","_xlfn.CHISQ.INV.RT":"CHISQ.INV.RT","_xlfn.CHISQ.TEST":"CHISQ.TEST","_xlfn.COMBINA":"COMBINA","_xlfn.CONFIDENCE.NORM":"CONFIDENCE.NORM","_xlfn.CONFIDENCE.T":"CONFIDENCE.T","_xlfn.COT":"COT","_xlfn.COTH":"COTH","_xlfn.COUNTIFS":"COUNTIFS","_xlfn.COVARIANCE.P":"COVARIANCE.P","_xlfn.COVARIANCE.S":"COVARIANCE.S","_xlfn.CSC":"CSC","_xlfn.CSCH":"CSCH","_xlfn.DAYS":"DAYS","_xlfn.DECIMAL":"DECIMAL","_xlfn.ECMA.CEILING":"ECMA.CEILING","_xlfn.ERF.PRECISE":"ERF.PRECISE","_xlfn.ERFC.PRECISE":"ERFC.PRECISE","_xlfn.EXPON.DIST":"EXPON.DIST","_xlfn.F.DIST":"F.DIST","_xlfn.F.DIST.RT":"F.DIST.RT","_xlfn.F.INV":"F.INV","_xlfn.F.INV.RT":"F.INV.RT","_xlfn.F.TEST":"F.TEST","_xlfn.FILTERXML":"FILTERXML","_xlfn.FLOOR.MATH":"FLOOR.MATH","_xlfn.FLOOR.PRECISE":"FLOOR.PRECISE","_xlfn.FORMULATEXT":"FORMULATEXT","_xlfn.GAMMA":"GAMMA","_xlfn.GAMMA.DIST":"GAMMA.DIST","_xlfn.GAMMA.INV":"GAMMA.INV","_xlfn.GAMMALN.PRECISE":"GAMMALN.PRECISE","_xlfn.GAUSS":"GAUSS","_xlfn.HYPGEOM.DIST":"HYPGEOM.DIST","_xlfn.IFNA":"IFNA","_xlfn.IFERROR":"IFERROR","_xlfn.IMCOSH":"IMCOSH","_xlfn.IMCOT":"IMCOT","_xlfn.IMCSC":"IMCSC","_xlfn.IMCSCH":"IMCSCH","_xlfn.IMSEC":"IMSEC","_xlfn.IMSECH":"IMSECH","_xlfn.IMSINH":"IMSINH","_xlfn.IMTAN":"IMTAN","_xlfn.ISFORMULA":"ISFORMULA","_xlfn.ISO.CEILING":"ISO.CEILING","_xlfn.ISOWEEKNUM":"ISOWEEKNUM","_xlfn.LOGNORM.DIST":"LOGNORM.DIST","_xlfn.LOGNORM.INV":"LOGNORM.INV","_xlfn.MODE.MULT":"MODE.MULT","_xlfn.MODE.SNGL":"MODE.SNGL","_xlfn.MUNIT":"MUNIT","_xlfn.NEGBINOM.DIST":"NEGBINOM.DIST","_xlfn.NETWORKDAYS.INTL":"NETWORKDAYS.INTL","_xlfn.NIGBINOM":"NIGBINOM","_xlfn.NORM.DIST":"NORM.DIST","_xlfn.NORM.INV":"NORM.INV","_xlfn.NORM.S.DIST":"NORM.S.DIST","_xlfn.NORM.S.INV":"NORM.S.INV","_xlfn.NUMBERVALUE":"NUMBERVALUE","_xlfn.PDURATION":"PDURATION","_xlfn.PERCENTILE.EXC":"PERCENTILE.EXC","_xlfn.PERCENTILE.INC":"PERCENTILE.INC","_xlfn.PERCENTRANK.EXC":"PERCENTRANK.EXC","_xlfn.PERCENTRANK.INC":"PERCENTRANK.INC","_xlfn.PERMUTATIONA":"PERMUTATIONA","_xlfn.PHI":"PHI","_xlfn.POISSON.DIST":"POISSON.DIST","_xlfn.QUARTILE.EXC":"QUARTILE.EXC","_xlfn.QUARTILE.INC":"QUARTILE.INC","_xlfn.QUERYSTRING":"QUERYSTRING","_xlfn.RANK.AVG":"RANK.AVG","_xlfn.RANK.EQ":"RANK.EQ","_xlfn.RRI":"RRI","_xlfn.SEC":"SEC","_xlfn.SECH":"SECH","_xlfn.SHEET":"SHEET","_xlfn.SHEETS":"SHEETS","_xlfn.SKEW.P":"SKEW.P","_xlfn.STDEV.P":"STDEV.P","_xlfn.STDEV.S":"STDEV.S","_xlfn.SUMIFS":"SUMIFS","_xlfn.T.DIST":"T.DIST","_xlfn.T.DIST.2T":"T.DIST.2T","_xlfn.T.DIST.RT":"T.DIST.RT","_xlfn.T.INV":"T.INV","_xlfn.T.INV.2T":"T.INV.2T","_xlfn.T.TEST":"T.TEST","_xlfn.UNICHAR":"UNICHAR","_xlfn.UNICODE":"UNICODE","_xlfn.VAR.P":"VAR.P","_xlfn.VAR.S":"VAR.S","_xlfn.WEBSERVICE":"WEBSERVICE","_xlfn.WEIBULL.DIST":"WEIBULL.DIST","_xlfn.WORKDAY.INTL":"WORKDAY.INTL","_xlfn.XOR":"XOR","_xlfn.Z.TEST":"Z.TEST"};var RecordEnum={6:{n:"Formula",f:parse_Formula},10:{n:"EOF",f:parse_EOF},12:{n:"CalcCount",f:parse_CalcCount},13:{n:"CalcMode",f:parse_CalcMode},14:{n:"CalcPrecision",f:parse_CalcPrecision},15:{n:"CalcRefMode",f:parse_CalcRefMode},16:{n:"CalcDelta",f:parse_CalcDelta},17:{n:"CalcIter",f:parse_CalcIter},18:{n:"Protect",f:parse_Protect},19:{n:"Password",f:parse_Password},20:{n:"Header",f:parse_Header},21:{n:"Footer",f:parse_Footer},23:{n:"ExternSheet",f:parse_ExternSheet},24:{n:"Lbl",f:parse_Lbl},25:{n:"WinProtect",f:parse_WinProtect},26:{n:"VerticalPageBreaks",f:parse_VerticalPageBreaks},27:{n:"HorizontalPageBreaks",f:parse_HorizontalPageBreaks},28:{n:"Note",f:parse_Note},29:{n:"Selection",f:parse_Selection},34:{n:"Date1904",f:parse_Date1904},35:{n:"ExternName",f:parse_ExternName},38:{n:"LeftMargin",f:parse_LeftMargin},39:{n:"RightMargin",f:parse_RightMargin},40:{n:"TopMargin",f:parse_TopMargin},41:{n:"BottomMargin",f:parse_BottomMargin},42:{n:"PrintRowCol",f:parse_PrintRowCol},43:{n:"PrintGrid",f:parse_PrintGrid},47:{n:"FilePass",f:parse_FilePass},49:{n:"Font",f:parse_Font},51:{n:"PrintSize",f:parse_PrintSize},60:{n:"Continue",f:parse_Continue},61:{n:"Window1",f:parse_Window1},64:{n:"Backup",f:parse_Backup},65:{n:"Pane",f:parse_Pane},66:{n:"CodePage",f:parse_CodePage},77:{n:"Pls",f:parse_Pls},80:{n:"DCon",f:parse_DCon},81:{n:"DConRef",f:parse_DConRef},82:{n:"DConName",f:parse_DConName},85:{n:"DefColWidth",f:parse_DefColWidth},89:{n:"XCT",f:parse_XCT},90:{n:"CRN",f:parse_CRN},91:{n:"FileSharing",f:parse_FileSharing},92:{n:"WriteAccess",f:parse_WriteAccess},93:{n:"Obj",f:parse_Obj},94:{n:"Uncalced",f:parse_Uncalced},95:{n:"CalcSaveRecalc",f:parse_CalcSaveRecalc},96:{n:"Template",f:parse_Template},97:{n:"Intl",f:parse_Intl},99:{n:"ObjProtect",f:parse_ObjProtect},125:{n:"ColInfo",f:parse_ColInfo},128:{n:"Guts",f:parse_Guts},129:{n:"WsBool",f:parse_WsBool},130:{n:"GridSet",f:parse_GridSet},131:{n:"HCenter",f:parse_HCenter},132:{n:"VCenter",f:parse_VCenter},133:{n:"BoundSheet8",f:parse_BoundSheet8},134:{n:"WriteProtect",f:parse_WriteProtect},140:{n:"Country",f:parse_Country},141:{n:"HideObj",f:parse_HideObj},144:{n:"Sort",f:parse_Sort},146:{n:"Palette",f:parse_Palette},151:{n:"Sync",f:parse_Sync},152:{n:"LPr",f:parse_LPr},153:{n:"DxGCol",f:parse_DxGCol},154:{n:"FnGroupName",f:parse_FnGroupName},155:{n:"FilterMode",f:parse_FilterMode},156:{n:"BuiltInFnGroupCount",f:parse_BuiltInFnGroupCount},157:{n:"AutoFilterInfo",f:parse_AutoFilterInfo},158:{n:"AutoFilter",f:parse_AutoFilter},160:{n:"Scl",f:parse_Scl},161:{n:"Setup",f:parse_Setup},174:{n:"ScenMan",f:parse_ScenMan},175:{n:"SCENARIO",f:parse_SCENARIO},176:{n:"SxView",f:parse_SxView},177:{n:"Sxvd",f:parse_Sxvd},178:{n:"SXVI",f:parse_SXVI},180:{n:"SxIvd",f:parse_SxIvd},181:{n:"SXLI",f:parse_SXLI},182:{n:"SXPI",f:parse_SXPI},184:{n:"DocRoute",f:parse_DocRoute},185:{n:"RecipName",f:parse_RecipName},189:{n:"MulRk",f:parse_MulRk},190:{n:"MulBlank",f:parse_MulBlank},193:{n:"Mms",f:parse_Mms},197:{n:"SXDI",f:parse_SXDI},198:{n:"SXDB",f:parse_SXDB},199:{n:"SXFDB",f:parse_SXFDB},200:{n:"SXDBB",f:parse_SXDBB},201:{n:"SXNum",f:parse_SXNum},202:{n:"SxBool",f:parse_SxBool},203:{n:"SxErr",f:parse_SxErr},204:{n:"SXInt",f:parse_SXInt},205:{n:"SXString",f:parse_SXString},206:{n:"SXDtr",f:parse_SXDtr},207:{n:"SxNil",f:parse_SxNil},208:{n:"SXTbl",f:parse_SXTbl},209:{n:"SXTBRGIITM",f:parse_SXTBRGIITM},210:{n:"SxTbpg",f:parse_SxTbpg},211:{n:"ObProj",f:parse_ObProj},213:{n:"SXStreamID",f:parse_SXStreamID},215:{n:"DBCell",f:parse_DBCell},216:{n:"SXRng",f:parse_SXRng},217:{n:"SxIsxoper",f:parse_SxIsxoper},218:{n:"BookBool",f:parse_BookBool},220:{n:"DbOrParamQry",f:parse_DbOrParamQry},221:{n:"ScenarioProtect",f:parse_ScenarioProtect},222:{n:"OleObjectSize",f:parse_OleObjectSize},224:{n:"XF",f:parse_XF},225:{n:"InterfaceHdr",f:parse_InterfaceHdr},226:{n:"InterfaceEnd",f:parse_InterfaceEnd},227:{n:"SXVS",f:parse_SXVS},229:{n:"MergeCells",f:parse_MergeCells},233:{n:"BkHim",f:parse_BkHim},235:{n:"MsoDrawingGroup",f:parse_MsoDrawingGroup},236:{n:"MsoDrawing",f:parse_MsoDrawing},237:{n:"MsoDrawingSelection",f:parse_MsoDrawingSelection},239:{n:"PhoneticInfo",f:parse_PhoneticInfo},240:{n:"SxRule",f:parse_SxRule},241:{n:"SXEx",f:parse_SXEx},242:{n:"SxFilt",f:parse_SxFilt},244:{n:"SxDXF",f:parse_SxDXF},245:{n:"SxItm",f:parse_SxItm},246:{n:"SxName",f:parse_SxName},247:{n:"SxSelect",f:parse_SxSelect},248:{n:"SXPair",f:parse_SXPair},249:{n:"SxFmla",f:parse_SxFmla},251:{n:"SxFormat",f:parse_SxFormat},252:{n:"SST",f:parse_SST},253:{n:"LabelSst",f:parse_LabelSst},255:{n:"ExtSST",f:parse_ExtSST},256:{n:"SXVDEx",f:parse_SXVDEx},259:{n:"SXFormula",f:parse_SXFormula},290:{n:"SXDBEx",f:parse_SXDBEx},311:{n:"RRDInsDel",f:parse_RRDInsDel},312:{n:"RRDHead",f:parse_RRDHead},315:{n:"RRDChgCell",f:parse_RRDChgCell},317:{n:"RRTabId",f:parse_RRTabId},318:{n:"RRDRenSheet",f:parse_RRDRenSheet},319:{n:"RRSort",f:parse_RRSort},320:{n:"RRDMove",f:parse_RRDMove},330:{n:"RRFormat",f:parse_RRFormat},331:{n:"RRAutoFmt",f:parse_RRAutoFmt},333:{n:"RRInsertSh",f:parse_RRInsertSh},334:{n:"RRDMoveBegin",f:parse_RRDMoveBegin},335:{n:"RRDMoveEnd",f:parse_RRDMoveEnd},336:{n:"RRDInsDelBegin",f:parse_RRDInsDelBegin},337:{n:"RRDInsDelEnd",f:parse_RRDInsDelEnd},338:{n:"RRDConflict",f:parse_RRDConflict},339:{n:"RRDDefName",f:parse_RRDDefName},340:{n:"RRDRstEtxp",f:parse_RRDRstEtxp},351:{n:"LRng",f:parse_LRng},352:{n:"UsesELFs",f:parse_UsesELFs},353:{n:"DSF",f:parse_DSF},401:{n:"CUsr",f:parse_CUsr},402:{n:"CbUsr",f:parse_CbUsr},403:{n:"UsrInfo",f:parse_UsrInfo},404:{n:"UsrExcl",f:parse_UsrExcl},405:{n:"FileLock",f:parse_FileLock},406:{n:"RRDInfo",f:parse_RRDInfo},407:{n:"BCUsrs",f:parse_BCUsrs},408:{n:"UsrChk",f:parse_UsrChk},425:{n:"UserBView",f:parse_UserBView},426:{n:"UserSViewBegin",f:parse_UserSViewBegin},427:{n:"UserSViewEnd",f:parse_UserSViewEnd},428:{n:"RRDUserView",f:parse_RRDUserView},429:{n:"Qsi",f:parse_Qsi},430:{n:"SupBook",f:parse_SupBook},431:{n:"Prot4Rev",f:parse_Prot4Rev},432:{n:"CondFmt",f:parse_CondFmt},433:{n:"CF",f:parse_CF},434:{n:"DVal",f:parse_DVal},437:{n:"DConBin",f:parse_DConBin},438:{n:"TxO",f:parse_TxO},439:{n:"RefreshAll",f:parse_RefreshAll},440:{n:"HLink",f:parse_HLink},441:{n:"Lel",f:parse_Lel},442:{n:"CodeName",f:parse_CodeName},443:{n:"SXFDBType",f:parse_SXFDBType},444:{n:"Prot4RevPass",f:parse_Prot4RevPass},445:{n:"ObNoMacros",f:parse_ObNoMacros},446:{n:"Dv",f:parse_Dv},448:{n:"Excel9File",f:parse_Excel9File},449:{n:"RecalcId",f:parse_RecalcId,r:2},450:{n:"EntExU2",f:parse_EntExU2},512:{n:"Dimensions",f:parse_Dimensions},513:{n:"Blank",f:parse_Blank},515:{n:"Number",f:parse_Number},516:{n:"Label",f:parse_Label},517:{n:"BoolErr",f:parse_BoolErr},519:{n:"String",f:parse_String},520:{n:"Row",f:parse_Row},523:{n:"Index",f:parse_Index},545:{n:"Array",f:parse_Array},549:{n:"DefaultRowHeight",f:parse_DefaultRowHeight},566:{n:"Table",f:parse_Table},574:{n:"Window2",f:parse_Window2},638:{n:"RK",f:parse_RK},659:{n:"Style",f:parse_Style},1048:{n:"BigName",f:parse_BigName},1054:{n:"Format",f:parse_Format},1084:{n:"ContinueBigName",f:parse_ContinueBigName},1212:{n:"ShrFmla",f:parse_ShrFmla},2048:{n:"HLinkTooltip",f:parse_HLinkTooltip},2049:{n:"WebPub",f:parse_WebPub},2050:{n:"QsiSXTag",f:parse_QsiSXTag},2051:{n:"DBQueryExt",f:parse_DBQueryExt},2052:{n:"ExtString",f:parse_ExtString},2053:{n:"TxtQry",f:parse_TxtQry},2054:{n:"Qsir",f:parse_Qsir},2055:{n:"Qsif",f:parse_Qsif},2056:{n:"RRDTQSIF",f:parse_RRDTQSIF},2057:{n:"BOF",f:parse_BOF},2058:{n:"OleDbConn",f:parse_OleDbConn},2059:{n:"WOpt",f:parse_WOpt},2060:{n:"SXViewEx",f:parse_SXViewEx},2061:{n:"SXTH",f:parse_SXTH},2062:{n:"SXPIEx",f:parse_SXPIEx},2063:{n:"SXVDTEx",f:parse_SXVDTEx},2064:{n:"SXViewEx9",f:parse_SXViewEx9},2066:{n:"ContinueFrt",f:parse_ContinueFrt},2067:{n:"RealTimeData",f:parse_RealTimeData},2128:{n:"ChartFrtInfo",f:parse_ChartFrtInfo},2129:{n:"FrtWrapper",f:parse_FrtWrapper},2130:{n:"StartBlock",f:parse_StartBlock},2131:{n:"EndBlock",f:parse_EndBlock},2132:{n:"StartObject",f:parse_StartObject},2133:{n:"EndObject",f:parse_EndObject},2134:{n:"CatLab",f:parse_CatLab},2135:{n:"YMult",f:parse_YMult},2136:{n:"SXViewLink",f:parse_SXViewLink},2137:{n:"PivotChartBits",f:parse_PivotChartBits},2138:{n:"FrtFontList",f:parse_FrtFontList},2146:{n:"SheetExt",f:parse_SheetExt},2147:{n:"BookExt",f:parse_BookExt,r:12},2148:{n:"SXAddl",f:parse_SXAddl},2149:{n:"CrErr",f:parse_CrErr},2150:{n:"HFPicture",f:parse_HFPicture},2151:{n:"FeatHdr",f:parse_FeatHdr},2152:{n:"Feat",f:parse_Feat},2154:{n:"DataLabExt",f:parse_DataLabExt},2155:{n:"DataLabExtContents",f:parse_DataLabExtContents},2156:{n:"CellWatch",f:parse_CellWatch},2161:{n:"FeatHdr11",f:parse_FeatHdr11},2162:{n:"Feature11",f:parse_Feature11},2164:{n:"DropDownObjIds",f:parse_DropDownObjIds},2165:{n:"ContinueFrt11",f:parse_ContinueFrt11},2166:{n:"DConn",f:parse_DConn},2167:{n:"List12",f:parse_List12},2168:{n:"Feature12",f:parse_Feature12},2169:{n:"CondFmt12",f:parse_CondFmt12},2170:{n:"CF12",f:parse_CF12},2171:{n:"CFEx",f:parse_CFEx},2172:{n:"XFCRC",f:parse_XFCRC},2173:{n:"XFExt",f:parse_XFExt},2174:{n:"AutoFilter12",f:parse_AutoFilter12},2175:{n:"ContinueFrt12",f:parse_ContinueFrt12},2180:{n:"MDTInfo",f:parse_MDTInfo},2181:{n:"MDXStr",f:parse_MDXStr},2182:{n:"MDXTuple",f:parse_MDXTuple},2183:{n:"MDXSet",f:parse_MDXSet},2184:{n:"MDXProp",f:parse_MDXProp},2185:{n:"MDXKPI",f:parse_MDXKPI},2186:{n:"MDB",f:parse_MDB},2187:{n:"PLV",f:parse_PLV},2188:{n:"Compat12",f:parse_Compat12,r:12},2189:{n:"DXF",f:parse_DXF},2190:{n:"TableStyles",f:parse_TableStyles,r:12},2191:{n:"TableStyle",f:parse_TableStyle},2192:{n:"TableStyleElement",f:parse_TableStyleElement},2194:{n:"StyleExt",f:parse_StyleExt},2195:{n:"NamePublish",f:parse_NamePublish},2196:{n:"NameCmt",f:parse_NameCmt},2197:{n:"SortData",f:parse_SortData},2198:{n:"Theme",f:parse_Theme},2199:{n:"GUIDTypeLib",f:parse_GUIDTypeLib},2200:{n:"FnGrp12",f:parse_FnGrp12},2201:{n:"NameFnGrp12",f:parse_NameFnGrp12},2202:{n:"MTRSettings",f:parse_MTRSettings,r:12},2203:{n:"CompressPictures",f:parse_CompressPictures},2204:{n:"HeaderFooter",f:parse_HeaderFooter},2205:{n:"CrtLayout12",f:parse_CrtLayout12},2206:{n:"CrtMlFrt",f:parse_CrtMlFrt},2207:{n:"CrtMlFrtContinue",f:parse_CrtMlFrtContinue},2211:{n:"ForceFullCalculation",f:parse_ForceFullCalculation},2212:{n:"ShapePropsStream",f:parse_ShapePropsStream},2213:{n:"TextPropsStream",f:parse_TextPropsStream},2214:{n:"RichTextStream",f:parse_RichTextStream},2215:{n:"CrtLayout12A",f:parse_CrtLayout12A},4097:{n:"Units",f:parse_Units},4098:{n:"Chart",f:parse_Chart},4099:{n:"Series",f:parse_Series},4102:{n:"DataFormat",f:parse_DataFormat},4103:{n:"LineFormat",f:parse_LineFormat},4105:{n:"MarkerFormat",f:parse_MarkerFormat},4106:{n:"AreaFormat",f:parse_AreaFormat},4107:{n:"PieFormat",f:parse_PieFormat},4108:{n:"AttachedLabel",f:parse_AttachedLabel},4109:{n:"SeriesText",f:parse_SeriesText},4116:{n:"ChartFormat",f:parse_ChartFormat},4117:{n:"Legend",f:parse_Legend},4118:{n:"SeriesList",f:parse_SeriesList},4119:{n:"Bar",f:parse_Bar},4120:{n:"Line",f:parse_Line},4121:{n:"Pie",f:parse_Pie},4122:{n:"Area",f:parse_Area},4123:{n:"Scatter",f:parse_Scatter},4124:{n:"CrtLine",f:parse_CrtLine},4125:{n:"Axis",f:parse_Axis},4126:{n:"Tick",f:parse_Tick},4127:{n:"ValueRange",f:parse_ValueRange},4128:{n:"CatSerRange",f:parse_CatSerRange},4129:{n:"AxisLine",f:parse_AxisLine},4130:{n:"CrtLink",f:parse_CrtLink},4132:{n:"DefaultText",f:parse_DefaultText},4133:{n:"Text",f:parse_Text},4134:{n:"FontX",f:parse_FontX},4135:{n:"ObjectLink",f:parse_ObjectLink},4146:{n:"Frame",f:parse_Frame},4147:{n:"Begin",f:parse_Begin},4148:{n:"End",f:parse_End},4149:{n:"PlotArea",f:parse_PlotArea},4154:{n:"Chart3d",f:parse_Chart3d},4156:{n:"PicF",f:parse_PicF},4157:{n:"DropBar",f:parse_DropBar},4158:{n:"Radar",f:parse_Radar},4159:{n:"Surf",f:parse_Surf},4160:{n:"RadarArea",f:parse_RadarArea},4161:{n:"AxisParent",f:parse_AxisParent},4163:{n:"LegendException",f:parse_LegendException},4164:{n:"ShtProps",f:parse_ShtProps},4165:{n:"SerToCrt",f:parse_SerToCrt},4166:{n:"AxesUsed",f:parse_AxesUsed},4168:{n:"SBaseRef",f:parse_SBaseRef},4170:{n:"SerParent",f:parse_SerParent},4171:{n:"SerAuxTrend",f:parse_SerAuxTrend},4174:{n:"IFmtRecord",f:parse_IFmtRecord},4175:{n:"Pos",f:parse_Pos},4176:{n:"AlRuns",f:parse_AlRuns},4177:{n:"BRAI",f:parse_BRAI},4187:{n:"SerAuxErrBar",f:parse_SerAuxErrBar},4188:{n:"ClrtClient",f:parse_ClrtClient},4189:{n:"SerFmt",f:parse_SerFmt},4191:{n:"Chart3DBarShape",f:parse_Chart3DBarShape},4192:{n:"Fbi",f:parse_Fbi},4193:{n:"BopPop",f:parse_BopPop},4194:{n:"AxcExt",f:parse_AxcExt},4195:{n:"Dat",f:parse_Dat},4196:{n:"PlotGrowth",f:parse_PlotGrowth},4197:{n:"SIIndex",f:parse_SIIndex},4198:{n:"GelFrame",f:parse_GelFrame},4199:{n:"BopPopCustom",f:parse_BopPopCustom},4200:{n:"Fbi2",f:parse_Fbi2},22:{n:"ExternCount",f:parsenoop},126:{n:"RK",f:parsenoop},127:{n:"ImData",f:parsenoop},135:{n:"Addin",f:parsenoop},136:{n:"Edg",f:parsenoop},137:{n:"Pub",f:parsenoop},145:{n:"Sub",f:parsenoop},148:{n:"LHRecord",f:parsenoop},149:{n:"LHNGraph",f:parsenoop},150:{n:"Sound",f:parsenoop},169:{n:"CoordList",f:parsenoop},171:{n:"GCW",f:parsenoop},188:{n:"ShrFmla",f:parsenoop},194:{n:"AddMenu",f:parsenoop},195:{n:"DelMenu",f:parsenoop},214:{n:"RString",f:parsenoop},223:{n:"UDDesc",f:parsenoop},234:{n:"TabIdConf",f:parsenoop},354:{n:"XL5Modify",f:parsenoop},421:{n:"FileSharing2",f:parsenoop},536:{n:"Name",f:parsenoop},547:{n:"ExternName",f:parse_ExternName},561:{n:"Font",f:parsenoop},1030:{n:"Formula",f:parse_Formula},2157:{n:"FeatInfo",f:parsenoop},2163:{n:"FeatInfo11",f:parsenoop},2177:{n:"SXAddl12",f:parsenoop},2240:{n:"AutoWebPub",f:parsenoop},2241:{n:"ListObj",f:parsenoop},2242:{n:"ListField",f:parsenoop},2243:{n:"ListDV",f:parsenoop},2244:{n:"ListCondFmt",f:parsenoop},2245:{n:"ListCF",f:parsenoop},2246:{n:"FMQry",f:parsenoop},2247:{n:"FMSQry",f:parsenoop},2248:{n:"PLV",f:parsenoop},2249:{n:"LnExt",f:parsenoop},2250:{n:"MkrExt",f:parsenoop},2251:{n:"CrtCoopt",f:parsenoop},0:{}};var CountryEnum={1:"US",2:"CA",3:"",7:"RU",20:"EG",30:"GR",31:"NL",32:"BE",33:"FR",34:"ES",36:"HU",39:"IT",41:"CH",43:"AT",44:"GB",45:"DK",46:"SE",47:"NO",48:"PL",49:"DE",52:"MX",55:"BR",61:"AU",64:"NZ",66:"TH",81:"JP",82:"KR",84:"VN",86:"CN",90:"TR",105:"JS",213:"DZ",216:"MA",218:"LY",351:"PT",354:"IS",358:"FI",420:"CZ",886:"TW",961:"LB",962:"JO",963:"SY",964:"IQ",965:"KW",966:"SA",971:"AE",972:"IL",974:"QA",981:"IR",65535:"US"};function fix_opts_func(defaults){return function fix_opts(opts){for(var i=0;i!=defaults.length;++i){var d=defaults[i];if(typeof opts[d[0]]==="undefined")opts[d[0]]=d[1];if(d[2]==="n")opts[d[0]]=Number(opts[d[0]])}}}var fixopts=fix_opts_func([["cellNF",false],["cellFormula",true],["sheetRows",0,"n"],["bookSheets",false],["bookProps",false],["bookFiles",false],["password",""],["WTF",false]]);function parse_compobj(obj){var v={};var o=obj.content;var l=28,m;m=__lpstr(o,l);l+=4+__readUInt32LE(o,l);v.UserType=m;m=__readUInt32LE(o,l);l+=4;switch(m){case 0:break;case 4294967295:case 4294967294:l+=4;break;default:if(m>400)throw new Error("Unsupported Clipboard: "+m.toString(16));l+=m}m=__lpstr(o,l);l+=m.length===0?0:5+m.length;v.Reserved1=m;if((m=__readUInt32LE(o,l))!==1907550708)return v;throw"Unsupported Unicode Extension"}function parse_xlscfb(cfb,options){if(!options)options={};fixopts(options);reset_cp();var CompObj=cfb.find("!CompObj");var Summary=cfb.find("!SummaryInformation");var Workbook=cfb.find("/Workbook");if(!Workbook)Workbook=cfb.find("/Book");var CompObjP,SummaryP,WorkbookP;function slurp(R,blob,length,opts){var l=length;var bufs=[];var d=blob.slice(blob.l,blob.l+l);if(opts.enc&&opts.enc.insitu_decrypt)switch(R.n){case"BOF":case"FilePass":case"FileLock":case"InterfaceHdr":case"RRDInfo":case"RRDHead":case"UsrExcl":break;default:if(d.length===0)break;opts.enc.insitu_decrypt(d)}bufs.push(d);blob.l+=l;var next=RecordEnum[__readUInt16LE(blob,blob.l)];while(next!=null&&next.n==="Continue"){l=__readUInt16LE(blob,blob.l+2);bufs.push(blob.slice(blob.l+4,blob.l+4+l));blob.l+=4+l;next=RecordEnum[__readUInt16LE(blob,blob.l)]}var b=bconcat(bufs);prep_blob(b,0);var ll=0;b.lens=[];for(var j=0;j<bufs.length;++j){b.lens.push(ll);ll+=bufs[j].length}return R.f(b,b.length,opts)}function safe_format_xf(p,opts){if(!p.XF)return;try{var fmtid=p.XF.ifmt||0;if(fmtid===0){if(p.t==="n"){if((p.v|0)===p.v)p.w=SSF._general_int(p.v);else p.w=SSF._general_num(p.v)}else p.w=SSF._general(p.v)}else p.w=SSF.format(fmtid,p.v);if(opts.cellNF)p.z=SSF._table[fmtid]}catch(e){if(opts.WTF)throw e}}function make_cell(val,ixfe,t){return{v:val,ixfe:ixfe,t:t}}function parse_workbook(blob,options){var wb={opts:{}};var Sheets={};var out={};var Directory={};var found_sheet=false;var range={};var last_formula=null;var sst=[];var cur_sheet="";var Preamble={};var lastcell,last_cell,cc,cmnt,rng,rngC,rngR;var shared_formulae={};var array_formulae=[];var temp_val;var country;var cell_valid=true;var XFs=[];var addline=function addline(cell,line,options){if(!cell_valid)return;lastcell=cell;last_cell=encode_cell(cell);if(range.s){if(cell.r<range.s.r)range.s.r=cell.r;if(cell.c<range.s.c)range.s.c=cell.c}if(range.e){if(cell.r+1>range.e.r)range.e.r=cell.r+1;if(cell.c+1>range.e.c)range.e.c=cell.c+1}if(options.sheetRows&&lastcell.r>=options.sheetRows)cell_valid=false;else out[last_cell]=line};var opts={enc:false,sbcch:0,snames:[],sharedf:shared_formulae,arrayf:array_formulae,rrtabid:[],lastuser:"",biff:8,codepage:0,winlocked:0,wtf:false};if(options.password)opts.password=options.password;var mergecells=[];var objects=[];var supbooks=[[]];var sbc=0,sbci=0,sbcli=0;supbooks.SheetNames=opts.snames;supbooks.sharedf=opts.sharedf;supbooks.arrayf=opts.arrayf;var last_Rn="";var file_depth=0;while(blob.l<blob.length-1){var s=blob.l;var RecordType=blob.read_shift(2);if(RecordType===0&&last_Rn==="EOF")break;var length=blob.l===blob.length?0:blob.read_shift(2),y;var R=RecordEnum[RecordType];if(R&&R.f){if(options.bookSheets){if(last_Rn==="BoundSheet8"&&R.n!=="BoundSheet8")break}last_Rn=R.n;if(R.r===2||R.r==12){var rt=blob.read_shift(2);length-=2;if(!opts.enc&&rt!==RecordType)throw"rt mismatch";if(R.r==12){blob.l+=10;length-=10}}var val;if(R.n==="EOF")val=R.f(blob,length,opts);else val=slurp(R,blob,length,opts);var Rn=R.n;if(opts.biff===5)switch(Rn){case"Lbl":Rn="Label";break}switch(Rn){case"Date1904":wb.opts.Date1904=val;break;case"WriteProtect":wb.opts.WriteProtect=true;break;case"FilePass":if(!opts.enc)blob.l=0;opts.enc=val;if(opts.WTF)console.error(val);if(!options.password)throw new Error("File is password-protected");if(val.Type!==0)throw new Error("Encryption scheme unsupported");if(!val.valid)throw new Error("Password is incorrect");break;case"WriteAccess":opts.lastuser=val;break;case"FileSharing":break;case"CodePage":if(val===21010)val=1200;opts.codepage=val;set_cp(val);break;case"RRTabId":opts.rrtabid=val;break;case"WinProtect":opts.winlocked=val;break;case"Template":break;case"RefreshAll":wb.opts.RefreshAll=val;break;case"BookBool":break;case"UsesELFs":break;case"MTRSettings":{if(val[0]&&val[1])throw"Unsupported threads: "+val}break;case"CalcCount":wb.opts.CalcCount=val;break;case"CalcDelta":wb.opts.CalcDelta=val;break;case"CalcIter":wb.opts.CalcIter=val;break;case"CalcMode":wb.opts.CalcMode=val;break;case"CalcPrecision":wb.opts.CalcPrecision=val;break;case"CalcSaveRecalc":wb.opts.CalcSaveRecalc=val;break;case"CalcRefMode":opts.CalcRefMode=val;break;case"Uncalced":break;case"ForceFullCalculation":wb.opts.FullCalc=val;break;case"WsBool":break;case"XF":XFs.push(val);break;case"ExtSST":break;case"BookExt":break;case"RichTextStream":break;case"BkHim":break;case"SupBook":supbooks[++sbc]=[val];sbci=0;break;case"ExternName":supbooks[sbc][++sbci]=val;break;case"Index":break;case"Lbl":supbooks[0][++sbcli]=val;break;case"ExternSheet":supbooks[sbc]=supbooks[sbc].concat(val);sbci+=val.length;break;case"Protect":out["!protect"]=val;break;case"Password":if(val!==0&&opts.WTF)console.error("Password verifier: "+val);break;case"Prot4Rev":case"Prot4RevPass":break;case"BoundSheet8":{Directory[val.pos]=val;opts.snames.push(val.name)}break;case"EOF":{if(--file_depth)break;if(range.e){out["!range"]=range;if(range.e.r>0&&range.e.c>0){range.e.r--;range.e.c--;out["!ref"]=encode_range(range);range.e.r++;range.e.c++}if(mergecells.length>0)out["!merges"]=mergecells;if(objects.length>0)out["!objects"]=objects}if(cur_sheet==="")Preamble=out;else Sheets[cur_sheet]=out;out={}}break;case"BOF":{if(val.BIFFVer===1280)opts.biff=5;if(file_depth++)break;cell_valid=true;out={};cur_sheet=(Directory[s]||{name:""}).name;mergecells=[];objects=[]}break;case"Number":{temp_val={ixfe:val.ixfe,XF:XFs[val.ixfe],v:val.val,t:"n"};if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:val.c,r:val.r},temp_val,options)}break;case"BoolErr":{temp_val={ixfe:val.ixfe,XF:XFs[val.ixfe],v:val.val,t:val.t};if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:val.c,r:val.r},temp_val,options)}break;case"RK":{temp_val={ixfe:val.ixfe,XF:XFs[val.ixfe],v:val.rknum,t:"n"};if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:val.c,r:val.r},temp_val,options)}break;case"MulRk":{for(var j=val.c;j<=val.C;++j){var ixfe=val.rkrec[j-val.c][0];temp_val={ixfe:ixfe,XF:XFs[ixfe],v:val.rkrec[j-val.c][1],t:"n"};if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:j,r:val.r},temp_val,options)}}break;case"Formula":{switch(val.val){case"String":last_formula=val;break;case"Array Formula":throw"Array Formula unsupported";default:temp_val={v:val.val,ixfe:val.cell.ixfe,t:val.tt};temp_val.XF=XFs[temp_val.ixfe];if(options.cellFormula)temp_val.f="="+stringify_formula(val.formula,range,val.cell,supbooks,opts);if(temp_val.XF)safe_format_xf(temp_val,options);addline(val.cell,temp_val,options);last_formula=val}}break;case"String":{if(last_formula){last_formula.val=val;temp_val={v:last_formula.val,ixfe:last_formula.cell.ixfe,t:"s"};temp_val.XF=XFs[temp_val.ixfe];if(options.cellFormula)temp_val.f="="+stringify_formula(last_formula.formula,range,last_formula.cell,supbooks,opts);if(temp_val.XF)safe_format_xf(temp_val,options);addline(last_formula.cell,temp_val,options);last_formula=null}}break;case"Array":{array_formulae.push(val)}break;case"ShrFmla":{if(!cell_valid)break;shared_formulae[encode_cell(last_formula.cell)]=val[0]}break;case"LabelSst":temp_val=make_cell(sst[val.isst].t,val.ixfe,"s");temp_val.XF=XFs[temp_val.ixfe];if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:val.c,r:val.r},temp_val,options);break;case"Label":temp_val=make_cell(val.val,val.ixfe,"s");temp_val.XF=XFs[temp_val.ixfe];
18562 if(temp_val.XF)safe_format_xf(temp_val,options);addline({c:val.c,r:val.r},temp_val,options);break;case"Dimensions":{if(file_depth===1)range=val}break;case"SST":{sst=val}break;case"Format":{SSF.load(val[1],val[0])}break;case"MergeCells":mergecells=mergecells.concat(val);break;case"Obj":objects[val.cmo[0]]=opts.lastobj=val;break;case"TxO":opts.lastobj.TxO=val;break;case"HLink":{for(rngR=val[0].s.r;rngR<=val[0].e.r;++rngR)for(rngC=val[0].s.c;rngC<=val[0].e.c;++rngC)if(out[encode_cell({c:rngC,r:rngR})])out[encode_cell({c:rngC,r:rngR})].l=val[1]}break;case"HLinkTooltip":{for(rngR=val[0].s.r;rngR<=val[0].e.r;++rngR)for(rngC=val[0].s.c;rngC<=val[0].e.c;++rngC)if(out[encode_cell({c:rngC,r:rngR})])out[encode_cell({c:rngC,r:rngR})].l.tooltip=val[1]}break;case"Note":{if(opts.biff===5)break;cc=out[encode_cell(val[0])];var noteobj=objects[val[2]];if(!cc)break;if(!cc.c)cc.c=[];cmnt={a:val[1],t:noteobj.TxO.t};cc.c.push(cmnt)}break;case"NameCmt":break;default:switch(R.n){case"Header":break;case"Footer":break;case"HCenter":break;case"VCenter":break;case"Pls":break;case"Setup":break;case"DefColWidth":break;case"GCW":break;case"LHRecord":break;case"ColInfo":break;case"Row":break;case"DBCell":break;case"MulBlank":break;case"EntExU2":break;case"SxView":break;case"Sxvd":break;case"SXVI":break;case"SXVDEx":break;case"SxIvd":break;case"SXDI":break;case"SXLI":break;case"SXEx":break;case"QsiSXTag":break;case"Selection":break;case"Feat":break;case"FeatHdr":case"FeatHdr11":break;case"Feature11":case"Feature12":case"List12":break;case"Blank":break;case"Country":country=val;break;case"RecalcId":break;case"DefaultRowHeight":case"DxGCol":break;case"Fbi":case"Fbi2":case"GelFrame":break;case"Font":break;case"XFCRC":break;case"XFExt":break;case"Style":break;case"StyleExt":break;case"Palette":break;case"ClrtClient":break;case"Theme":break;case"ScenarioProtect":break;case"ObjProtect":break;case"CondFmt12":break;case"Table":break;case"TableStyles":break;case"TableStyle":break;case"TableStyleElement":break;case"SXStreamID":break;case"SXVS":break;case"DConRef":break;case"SXAddl":break;case"DConName":break;case"SXPI":break;case"SxFormat":break;case"SxSelect":break;case"SxRule":break;case"SxFilt":break;case"SxItm":break;case"SxDXF":break;case"ScenMan":break;case"DCon":break;case"CellWatch":break;case"PrintRowCol":break;case"PrintGrid":break;case"PrintSize":break;case"XCT":break;case"CRN":break;case"Scl":{}break;case"SheetExt":{}break;case"SheetExtOptional":{}break;case"ObNoMacros":{}break;case"ObProj":{}break;case"CodeName":{}break;case"GUIDTypeLib":{}break;case"WOpt":break;case"PhoneticInfo":break;case"OleObjectSize":break;case"DXF":case"DXFN":case"DXFN12":case"DXFN12List":case"DXFN12NoCB":break;case"Dv":case"DVal":break;case"BRAI":case"Series":case"SeriesText":break;case"DConn":break;case"DbOrParamQry":break;case"DBQueryExt":break;case"IFmtRecord":break;case"CondFmt":case"CF":case"CF12":case"CFEx":break;case"Excel9File":break;case"Units":break;case"InterfaceHdr":case"Mms":case"InterfaceEnd":case"DSF":case"BuiltInFnGroupCount":case"Window1":case"Window2":case"HideObj":case"GridSet":case"Guts":case"UserBView":case"UserSViewBegin":case"UserSViewEnd":case"Pane":break;default:switch(R.n){case"Dat":case"Begin":case"End":case"StartBlock":case"EndBlock":case"Frame":case"Area":case"Axis":case"AxisLine":case"Tick":break;case"AxesUsed":case"CrtLayout12":case"CrtLayout12A":case"CrtLink":case"CrtLine":case"CrtMlFrt":break;case"LineFormat":case"AreaFormat":case"Chart":case"Chart3d":case"Chart3DBarShape":case"ChartFormat":case"ChartFrtInfo":break;case"PlotArea":case"PlotGrowth":break;case"SeriesList":case"SerParent":case"SerAuxTrend":break;case"DataFormat":case"SerToCrt":case"FontX":break;case"CatSerRange":case"AxcExt":case"SerFmt":break;case"ShtProps":break;case"DefaultText":case"Text":case"CatLab":break;case"DataLabExtContents":break;case"Legend":case"LegendException":break;case"Pie":case"Scatter":break;case"PieFormat":case"MarkerFormat":break;case"StartObject":case"EndObject":break;case"AlRuns":case"ObjectLink":break;case"SIIndex":break;case"AttachedLabel":break;case"Line":case"Bar":break;case"Surf":break;case"AxisParent":break;case"Pos":break;case"ValueRange":break;case"SXViewEx9":break;case"SXViewLink":break;case"PivotChartBits":break;case"SBaseRef":break;case"TextPropsStream":break;case"LnExt":break;case"MkrExt":break;case"CrtCoopt":break;case"Qsi":case"Qsif":case"Qsir":case"QsiSXTag":break;case"TxtQry":break;case"FilterMode":break;case"AutoFilter":case"AutoFilterInfo":break;case"AutoFilter12":break;case"DropDownObjIds":break;case"Sort":break;case"SortData":break;case"ShapePropsStream":break;case"MsoDrawing":case"MsoDrawingGroup":case"MsoDrawingSelection":break;case"ImData":break;case"WebPub":case"AutoWebPub":case"RightMargin":case"LeftMargin":case"TopMargin":case"BottomMargin":case"HeaderFooter":case"HFPicture":case"PLV":case"HorizontalPageBreaks":case"VerticalPageBreaks":case"Backup":case"CompressPictures":case"Compat12":break;case"Continue":case"ContinueFrt12":break;case"ExternCount":break;case"RString":break;case"TabIdConf":case"Radar":case"RadarArea":case"DropBar":case"Intl":case"CoordList":case"SerAuxErrBar":break;default:if(options.WTF)throw"Unrecognized Record "+R.n}}}}else blob.l+=length}var sheetnamesraw=Object.keys(Directory).sort(function(a,b){return Number(a)-Number(b)}).map(function(x){return Directory[x].name});var sheetnames=sheetnamesraw.slice();wb.Directory=sheetnamesraw;wb.SheetNames=sheetnamesraw;if(!options.bookSheets)wb.Sheets=Sheets;wb.Preamble=Preamble;wb.Strings=sst;wb.SSF=SSF.get_table();if(opts.enc)wb.Encryption=opts.enc;wb.Metadata={};if(country!==undefined)wb.Metadata.Country=country;return wb}if(CompObj)CompObjP=parse_compobj(CompObj);if(options.bookProps&&!options.bookSheets)WorkbookP={};else{if(Workbook)WorkbookP=parse_workbook(Workbook.content,options);else throw new Error("Cannot find Workbook stream")}parse_props(cfb);var props={};for(var y in cfb.Summary)props[y]=cfb.Summary[y];for(y in cfb.DocSummary)props[y]=cfb.DocSummary[y];WorkbookP.Props=WorkbookP.Custprops=props;if(options.bookFiles)WorkbookP.cfb=cfb;WorkbookP.CompObjP=CompObjP;return WorkbookP}function parse_props(cfb){var DSI=cfb.find("!DocumentSummaryInformation");if(DSI)try{cfb.DocSummary=parse_PropertySetStream(DSI,DocSummaryPIDDSI)}catch(e){}var SI=cfb.find("!SummaryInformation");if(SI)try{cfb.Summary=parse_PropertySetStream(SI,SummaryPIDSI)}catch(e){}}var encregex=/&[a-z]*;/g,coderegex=/_x([0-9a-fA-F]+)_/g;function coderepl(m,c){return _chr(parseInt(c,16))}function encrepl($$){return encodings[$$]}function unescapexml(s){if(s.indexOf("&")>-1)s=s.replace(encregex,encrepl);return s.indexOf("_")===-1?s:s.replace(coderegex,coderepl)}function parsexmlbool(value,tag){switch(value){case"1":case"true":case"TRUE":return true;default:return false}}function matchtag(f,g){return new RegExp("<"+f+'(?: xml:space="preserve")?>([^☃]*)</'+f+">",(g||"")+"m")}var entregex=/&#(\d+);/g;function entrepl($$,$1){return String.fromCharCode(parseInt($1,10))}function fixstr(str){return str.replace(entregex,entrepl)}var everted_BERR=evert(BERR);var magic_formats={"General Number":"General","General Date":SSF._table[22],"Long Date":"dddd, mmmm dd, yyyy","Medium Date":SSF._table[15],"Short Date":SSF._table[14],"Long Time":SSF._table[19],"Medium Time":SSF._table[18],"Short Time":SSF._table[20],Currency:'"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',Fixed:SSF._table[2],Standard:SSF._table[4],Percent:SSF._table[10],Scientific:SSF._table[11],"Yes/No":'"Yes";"Yes";"No";@',"True/False":'"True";"True";"False";@',"On/Off":'"Yes";"Yes";"No";@'};function xlml_format(format,value){var fmt=magic_formats[format]||unescapexml(format);if(fmt==="General")return SSF._general(value);return SSF.format(fmt,value)}function xlml_set_prop(Props,tag,val){switch(tag){case"Description":tag="Comments";break}Props[tag]=val}function xlml_set_custprop(Custprops,Rn,cp,val){switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]){case"boolean":val=parsexmlbool(val);break;case"i2":case"int":val=parseInt(val,10);break;case"r4":case"float":val=parseFloat(val);break;case"date":case"dateTime.tz":val=new Date(val);break;case"i8":case"string":case"fixed":case"uuid":case"bin.base64":break;default:throw"bad custprop:"+cp[0]}Custprops[unescapexml(Rn[3])]=val}function safe_format_xlml(cell,nf,o){try{if(nf==="General"){if(cell.t==="n"){if((cell.v|0)===cell.v)cell.w=SSF._general_int(cell.v);else cell.w=SSF._general_num(cell.v)}else cell.w=SSF._general(cell.v)}else cell.w=xlml_format(nf||"General",cell.v);if(o.cellNF)cell.z=magic_formats[nf]||nf||"General"}catch(e){if(o.WTF)throw e}}function parse_xlml_data(xml,ss,data,cell,base,styles,csty,o){var nf="General",sid=cell.StyleID;o=o||{};if(sid===undefined&&csty)sid=csty.StyleID;while(styles[sid]!==undefined){if(styles[sid].nf)nf=styles[sid].nf;if(!styles[sid].Parent)break;sid=styles[sid].Parent}switch(data.Type){case"Boolean":cell.t="b";cell.v=parsexmlbool(xml);break;case"String":cell.t="str";cell.r=fixstr(unescapexml(xml));cell.v=xml.indexOf("<")>-1?ss:cell.r;break;case"DateTime":cell.v=(Date.parse(xml)-new Date(Date.UTC(1899,11,30)))/(24*60*60*1e3);if(cell.v!==cell.v)cell.v=unescapexml(xml);else if(cell.v>=1&&cell.v<60)cell.v=cell.v-1;if(!nf||nf=="General")nf="yyyy-mm-dd";case"Number":if(cell.v===undefined)cell.v=+xml;if(!cell.t)cell.t="n";break;case"Error":cell.t="e";cell.v=xml;cell.w=xml;break;default:cell.t="s";cell.v=fixstr(ss);break}if(cell.t!=="e")safe_format_xlml(cell,nf,o);if(o.cellFormula!=null&&cell.Formula){cell.f=rc_to_a1(unescapexml(cell.Formula),base);cell.Formula=undefined}cell.ixfe=cell.StyleID!==undefined?cell.StyleID:"Default"}function xlml_clean_comment(comment){comment.t=comment.v;comment.v=comment.w=comment.ixfe=undefined}function xlml_normalize(d){if(has_buf&&Buffer.isBuffer(d))return d.toString("utf8");if(typeof d==="string")return d;throw"badf"}var xlmlregex=/<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/gm;function parse_xlml_xml(d,opts){var str=xlml_normalize(d);var Rn;var state=[],tmp;var sheets={},sheetnames=[],cursheet={},sheetname="";var table={},cell={},row={},dtag,didx;var c=0,r=0;var refguess={s:{r:1e6,c:1e6},e:{r:0,c:0}};var styles={},stag={};var ss="",fidx=0;var mergecells=[];var Props={},Custprops={},pidx=0,cp={};var comments=[],comment={};var cstys=[],csty;while(Rn=xlmlregex.exec(str))switch(Rn[3]){case"Data":if(state[state.length-1][1])break;if(Rn[1]==="/")parse_xlml_data(str.slice(didx,Rn.index),ss,dtag,state[state.length-1][0]=="Comment"?comment:cell,{c:c,r:r},styles,cstys[c],opts);else{ss="";dtag=parsexmltag(Rn[0]);didx=Rn.index+Rn[0].length}break;case"Cell":if(Rn[1]==="/"){if(comments.length>0)cell.c=comments;if((!opts.sheetRows||opts.sheetRows>r)&&cell.v!==undefined)cursheet[encode_col(c)+encode_row(r)]=cell;if(cell.HRef){cell.l={Target:cell.HRef,tooltip:cell.HRefScreenTip};cell.HRef=cell.HRefScreenTip=undefined}if(cell.MergeAcross||cell.MergeDown){var cc=c+(parseInt(cell.MergeAcross,10)|0);var rr=r+(parseInt(cell.MergeDown,10)|0);mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}})}++c;if(cell.MergeAcross)c+=+cell.MergeAcross}else{cell=parsexmltagobj(Rn[0]);if(cell.Index)c=+cell.Index-1;if(c<refguess.s.c)refguess.s.c=c;if(c>refguess.e.c)refguess.e.c=c;if(Rn[0].substr(-2)==="/>")++c;comments=[]}break;case"Row":if(Rn[1]==="/"||Rn[0].substr(-2)==="/>"){if(r<refguess.s.r)refguess.s.r=r;if(r>refguess.e.r)refguess.e.r=r;if(Rn[0].substr(-2)==="/>"){row=parsexmltag(Rn[0]);if(row.Index)r=+row.Index-1}c=0;++r}else{row=parsexmltag(Rn[0]);if(row.Index)r=+row.Index-1}break;case"Worksheet":if(Rn[1]==="/"){if((tmp=state.pop())[0]!==Rn[3])throw"Bad state: "+tmp;sheetnames.push(sheetname);if(refguess.s.r<=refguess.e.r&&refguess.s.c<=refguess.e.c)cursheet["!ref"]=encode_range(refguess);if(mergecells.length)cursheet["!merges"]=mergecells;sheets[sheetname]=cursheet}else{refguess={s:{r:1e6,c:1e6},e:{r:0,c:0}};r=c=0;state.push([Rn[3],false]);tmp=parsexmltag(Rn[0]);sheetname=tmp.Name;cursheet={};mergecells=[]}break;case"Table":if(Rn[1]==="/"){if((tmp=state.pop())[0]!==Rn[3])throw"Bad state: "+tmp}else if(Rn[0].slice(-2)=="/>")break;else{table=parsexmltag(Rn[0]);state.push([Rn[3],false]);cstys=[]}break;case"Style":if(Rn[1]==="/")styles[stag.ID]=stag;else stag=parsexmltag(Rn[0]);break;case"NumberFormat":stag.nf=parsexmltag(Rn[0]).Format||"General";break;case"Column":if(state[state.length-1][0]!=="Table")break;csty=parsexmltag(Rn[0]);cstys[csty.Index-1||cstys.length]=csty;for(var i=0;i<+csty.Span;++i)cstys[cstys.length]=csty;break;case"NamedRange":break;case"NamedCell":break;case"B":break;case"I":break;case"U":break;case"S":break;case"Sub":break;case"Sup":break;case"Span":break;case"Border":break;case"Alignment":break;case"Borders":break;case"Font":if(Rn[0].substr(-2)==="/>")break;else if(Rn[1]==="/")ss+=str.slice(fidx,Rn.index);else fidx=Rn.index+Rn[0].length;break;case"Interior":break;case"Protection":break;case"Author":case"Title":case"Description":case"Created":case"Keywords":case"Subject":case"Category":case"Company":case"LastAuthor":case"LastSaved":case"LastPrinted":case"Version":case"Revision":case"TotalTime":case"HyperlinkBase":case"Manager":if(Rn[0].substr(-2)==="/>")break;else if(Rn[1]==="/")xlml_set_prop(Props,Rn[3],str.slice(pidx,Rn.index));else pidx=Rn.index+Rn[0].length;break;case"Paragraphs":break;case"Styles":case"Workbook":if(Rn[1]==="/"){if((tmp=state.pop())[0]!==Rn[3])throw"Bad state: "+tmp}else state.push([Rn[3],false]);break;case"Comment":if(Rn[1]==="/"){if((tmp=state.pop())[0]!==Rn[3])throw"Bad state: "+tmp;xlml_clean_comment(comment);comments.push(comment)}else{state.push([Rn[3],false]);tmp=parsexmltag(Rn[0]);comment={a:tmp.Author}}break;case"Name":break;case"ComponentOptions":case"DocumentProperties":case"CustomDocumentProperties":case"OfficeDocumentSettings":case"PivotTable":case"PivotCache":case"Names":case"MapInfo":case"PageBreaks":case"QueryTable":case"DataValidation":case"AutoFilter":case"Sorting":case"Schema":case"data":case"ConditionalFormatting":case"SmartTagType":case"SmartTags":case"ExcelWorkbook":case"WorkbookOptions":case"WorksheetOptions":if(Rn[1]==="/"){if((tmp=state.pop())[0]!==Rn[3])throw"Bad state: "+tmp}else if(Rn[0].charAt(Rn[0].length-2)!=="/")state.push([Rn[3],true]);break;default:var seen=true;switch(state[state.length-1][0]){case"OfficeDocumentSettings":switch(Rn[3]){case"AllowPNG":break;case"RemovePersonalInformation":break;case"DownloadComponents":break;case"LocationOfComponents":break;case"Colors":break;case"Color":break;case"Index":break;case"RGB":break;case"PixelsPerInch":break;case"TargetScreenSize":break;case"ReadOnlyRecommended":break;default:seen=false}break;case"ComponentOptions":switch(Rn[3]){case"Toolbar":break;case"HideOfficeLogo":break;case"SpreadsheetAutoFit":break;case"Label":break;case"Caption":break;case"MaxHeight":break;case"MaxWidth":break;case"NextSheetNumber":break;default:seen=false}break;case"ExcelWorkbook":switch(Rn[3]){case"WindowHeight":break;case"WindowWidth":break;case"WindowTopX":break;case"WindowTopY":break;case"TabRatio":break;case"ProtectStructure":break;case"ProtectWindows":break;case"ActiveSheet":break;case"DisplayInkNotes":break;case"FirstVisibleSheet":break;case"SupBook":break;case"SheetName":break;case"SheetIndex":break;case"SheetIndexFirst":break;case"SheetIndexLast":break;case"Dll":break;case"AcceptLabelsInFormulas":break;case"DoNotSaveLinkValues":break;case"Date1904":break;case"Iteration":break;case"MaxIterations":break;case"MaxChange":break;case"Path":break;case"Xct":break;case"Count":break;case"SelectedSheets":break;case"Calculation":break;case"Uncalced":break;case"StartupPrompt":break;case"Crn":break;case"ExternName":break;case"Formula":break;case"ColFirst":break;case"ColLast":break;case"WantAdvise":break;case"Boolean":break;case"Error":break;case"Text":break;case"OLE":break;case"NoAutoRecover":break;case"PublishObjects":break;case"DoNotCalculateBeforeSave":break;case"Number":break;case"RefModeR1C1":break;case"EmbedSaveSmartTags":break;default:seen=false}break;case"WorkbookOptions":switch(Rn[3]){case"OWCVersion":break;case"Height":break;case"Width":break;default:seen=false}break;case"WorksheetOptions":switch(Rn[3]){case"Unsynced":break;case"Visible":break;case"Print":break;case"Panes":break;case"Scale":break;case"Pane":break;case"Number":break;case"Layout":break;case"Header":break;case"Footer":break;case"PageSetup":break;case"PageMargins":break;case"Selected":break;case"ProtectObjects":break;case"EnableSelection":break;case"ProtectScenarios":break;case"ValidPrinterInfo":break;case"HorizontalResolution":break;case"VerticalResolution":break;case"NumberofCopies":break;case"ActiveRow":break;case"ActiveCol":break;case"ActivePane":break;case"TopRowVisible":break;case"TopRowBottomPane":break;case"LeftColumnVisible":break;case"LeftColumnRightPane":break;case"FitToPage":break;case"RangeSelection":break;case"PaperSizeIndex":break;case"PageLayoutZoom":break;case"PageBreakZoom":break;case"FilterOn":break;case"DoNotDisplayGridlines":break;case"SplitHorizontal":break;case"SplitVertical":break;case"FreezePanes":break;case"FrozenNoSplit":break;case"FitWidth":break;case"FitHeight":break;case"CommentsLayout":break;case"Zoom":break;case"LeftToRight":break;case"Gridlines":break;case"AllowSort":break;case"AllowFilter":break;case"AllowInsertRows":break;case"AllowDeleteRows":break;case"AllowInsertCols":break;case"AllowDeleteCols":break;case"AllowInsertHyperlinks":break;case"AllowFormatCells":break;case"AllowSizeCols":break;case"AllowSizeRows":break;case"NoSummaryRowsBelowDetail":break;case"TabColorIndex":break;case"DoNotDisplayHeadings":break;case"ShowPageLayoutZoom":break;case"NoSummaryColumnsRightDetail":break;case"BlackAndWhite":break;case"DoNotDisplayZeros":break;case"DisplayPageBreak":break;case"RowColHeadings":break;case"DoNotDisplayOutline":break;case"NoOrientation":break;case"AllowUsePivotTables":break;case"ZeroHeight":break;case"ViewableRange":break;case"Selection":break;case"ProtectContents":break;default:seen=false}break;case"PivotTable":case"PivotCache":switch(Rn[3]){case"ImmediateItemsOnDrop":break;case"ShowPageMultipleItemLabel":break;case"CompactRowIndent":break;case"Location":break;case"PivotField":break;case"Orientation":break;case"LayoutForm":break;case"LayoutSubtotalLocation":break;case"LayoutCompactRow":break;case"Position":break;case"PivotItem":break;case"DataType":break;case"DataField":break;case"SourceName":break;case"ParentField":break;case"PTLineItems":break;case"PTLineItem":break;case"CountOfSameItems":break;case"Item":break;case"ItemType":break;case"PTSource":break;case"CacheIndex":break;case"ConsolidationReference":break;case"FileName":break;case"Reference":break;case"NoColumnGrand":break;case"NoRowGrand":break;case"BlankLineAfterItems":break;case"Hidden":break;case"Subtotal":break;case"BaseField":break;case"MapChildItems":break;case"Function":break;case"RefreshOnFileOpen":break;case"PrintSetTitles":break;case"MergeLabels":break;case"DefaultVersion":break;case"RefreshName":break;case"RefreshDate":break;case"RefreshDateCopy":break;case"VersionLastRefresh":break;case"VersionLastUpdate":break;case"VersionUpdateableMin":break;case"VersionRefreshableMin":break;case"Calculation":break;default:seen=false}break;case"PageBreaks":switch(Rn[3]){case"ColBreaks":break;case"ColBreak":break;case"RowBreaks":break;case"RowBreak":break;case"ColStart":break;case"ColEnd":break;case"RowEnd":break;default:seen=false}break;case"AutoFilter":switch(Rn[3]){case"AutoFilterColumn":break;case"AutoFilterCondition":break;case"AutoFilterAnd":break;case"AutoFilterOr":break;default:seen=false}break;case"QueryTable":switch(Rn[3]){case"Id":break;case"AutoFormatFont":break;case"AutoFormatPattern":break;case"QuerySource":break;case"QueryType":break;case"EnableRedirections":break;case"RefreshedInXl9":break;case"URLString":break;case"HTMLTables":break;case"Connection":break;case"CommandText":break;case"RefreshInfo":break;case"NoTitles":break;case"NextId":break;case"ColumnInfo":break;case"OverwriteCells":break;case"DoNotPromptForFile":break;case"TextWizardSettings":break;case"Source":break;case"Number":break;case"Decimal":break;case"ThousandSeparator":break;case"TrailingMinusNumbers":break;case"FormatSettings":break;case"FieldType":break;case"Delimiters":break;case"Tab":break;case"Comma":break;case"AutoFormatName":break;case"VersionLastEdit":break;case"VersionLastRefresh":break;default:seen=false}break;case"Sorting":case"ConditionalFormatting":case"DataValidation":switch(Rn[3]){case"Range":break;case"Type":break;case"Min":break;case"Max":break;case"Sort":break;case"Descending":break;case"Order":break;case"CaseSensitive":break;case"Value":break;case"ErrorStyle":break;case"ErrorMessage":break;case"ErrorTitle":break;case"CellRangeList":break;case"InputMessage":break;case"InputTitle":break;case"ComboHide":break;case"InputHide":break;case"Condition":break;case"Qualifier":break;case"UseBlank":break;case"Value1":break;case"Value2":break;case"Format":break;default:seen=false}break;case"MapInfo":case"Schema":case"data":switch(Rn[3]){case"Map":break;case"Entry":break;case"Range":break;case"XPath":break;case"Field":break;case"XSDType":break;case"FilterOn":break;case"Aggregate":break;case"ElementType":break;case"AttributeType":break;case"schema":case"element":case"complexType":case"datatype":case"all":case"attribute":case"extends":break;case"row":break;default:seen=false}break;case"SmartTags":break;default:seen=false;break}if(seen)break;if(!state[state.length-1][1])throw"Unrecognized tag: "+Rn[3]+"|"+state.join("|");if(state[state.length-1][0]==="CustomDocumentProperties"){if(Rn[0].substr(-2)==="/>")break;else if(Rn[1]==="/")xlml_set_custprop(Custprops,Rn,cp,str.slice(pidx,Rn.index));else{cp=Rn;pidx=Rn.index+Rn[0].length}break}if(opts.WTF)throw"Unrecognized tag: "+Rn[3]+"|"+state.join("|")}var out={};if(!opts.bookSheets&&!opts.bookProps)out.Sheets=sheets;out.SheetNames=sheetnames;out.SSF=SSF.get_table();out.Props=Props;out.Custprops=Custprops;return out}function parse_xlml(data,opts){fixopts(opts=opts||{});switch(opts.type||"base64"){case"base64":return parse_xlml_xml(Base64.decode(data),opts);case"binary":case"buffer":case"file":return parse_xlml_xml(data,opts);case"array":return parse_xlml_xml(data.map(_chr).join(""),opts)}}function write_xlml(wb,opts){}var fs;if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){fs=require("fs")}}function firstbyte(f,o){switch((o||{}).type||"base64"){case"buffer":return f[0];case"base64":return Base64.decode(f.substr(0,12)).charCodeAt(0);case"binary":return f.charCodeAt(0);case"array":return f[0];default:throw new Error("Unrecognized type "+o.type)}}function xlsread(f,o){if(!o)o={};if(!o.type)o.type=has_buf&&Buffer.isBuffer(f)?"buffer":"base64";switch(firstbyte(f,o)){case 208:return parse_xlscfb(CFB.read(f,o),o);case 60:return parse_xlml(f,o);default:throw"Unsupported file"}}var readFile=function(f,o){var d=fs.readFileSync(f);if(!o)o={};switch(firstbyte(d,{type:"buffer"})){case 208:return parse_xlscfb(CFB.read(d,{type:"buffer"}),o);case 60:return parse_xlml(d,(o.type="buffer",o));default:throw"Unsupported file"}};function writeSync(wb,opts){var o=opts||{};switch(o.bookType){case"xml":return write_xlml(wb,o);default:throw"unsupported output format "+o.bookType}}function writeFileSync(wb,filename,opts){var o=opts|{};o.type="file";o.file=filename;switch(o.file.substr(-4).toLowerCase()){case".xls":o.bookType="xls";break;case".xml":o.bookType="xml";break}return writeSync(wb,o)}function shift_cell(cell,tgt){if(tgt.s){if(cell.cRel)cell.c+=tgt.s.c;if(cell.rRel)cell.r+=tgt.s.r}else{cell.c+=tgt.c;cell.r+=tgt.r}cell.cRel=cell.rRel=0;while(cell.c>=256)cell.c-=256;while(cell.r>=65536)cell.r-=65536;return cell}function shift_range(cell,range){cell.s=shift_cell(cell.s,range.s);cell.e=shift_cell(cell.e,range.s);return cell}function decode_row(rowstr){return parseInt(unfix_row(rowstr),10)-1}function encode_row(row){return""+(row+1)}function fix_row(cstr){return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2")}function unfix_row(cstr){return cstr.replace(/\$(\d+)$/,"$1")}function decode_col(colstr){var c=unfix_col(colstr),d=0,i=0;for(;i!==c.length;++i)d=26*d+c.charCodeAt(i)-64;return d-1}function encode_col(col){var s="";for(++col;col;col=Math.floor((col-1)/26))s=String.fromCharCode((col-1)%26+65)+s;return s}function fix_col(cstr){return cstr.replace(/^([A-Z])/,"$$$1")}function unfix_col(cstr){return cstr.replace(/^\$([A-Z])/,"$1")}function split_cell(cstr){return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(",")}function decode_cell(cstr){var splt=split_cell(cstr);return{c:decode_col(splt[0]),r:decode_row(splt[1])}}function encode_cell(cell){return encode_col(cell.c)+encode_row(cell.r)}function fix_cell(cstr){return fix_col(fix_row(cstr))}function unfix_cell(cstr){return unfix_col(unfix_row(cstr))}function decode_range(range){var x=range.split(":").map(decode_cell);return{s:x[0],e:x[x.length-1]}}function encode_range(cs,ce){if(ce===undefined||typeof ce==="number")return encode_range(cs.s,cs.e);if(typeof cs!=="string")cs=encode_cell(cs);if(typeof ce!=="string")ce=encode_cell(ce);return cs==ce?cs:cs+":"+ce}function safe_decode_range(range){var o={s:{c:0,r:0},e:{c:0,r:0}};var idx=0,i=0,cc=0;var len=range.length;for(idx=0;i<len;++i){if((cc=range.charCodeAt(i)-64)<1||cc>26)break;idx=26*idx+cc}o.s.c=--idx;for(idx=0;i<len;++i){if((cc=range.charCodeAt(i)-48)<0||cc>9)break;idx=10*idx+cc}o.s.r=--idx;if(i===len||range.charCodeAt(++i)===58){o.e.c=o.s.c;o.e.r=o.s.r;return o}for(idx=0;i!=len;++i){if((cc=range.charCodeAt(i)-64)<1||cc>26)break;idx=26*idx+cc}o.e.c=--idx;for(idx=0;i!=len;++i){if((cc=range.charCodeAt(i)-48)<0||cc>9)break;idx=10*idx+cc}o.e.r=--idx;return o}function safe_format_cell(cell,v){if(cell.z!==undefined)try{return cell.w=SSF.format(cell.z,v)}catch(e){}if(!cell.XF)return v;try{return cell.w=SSF.format(cell.XF.ifmt||0,v)}catch(e){return""+v}}function format_cell(cell,v){if(cell==null||cell.t==null)return"";if(cell.w!==undefined)return cell.w;if(v===undefined)return safe_format_cell(cell,cell.v);return safe_format_cell(cell,v)}function sheet_to_json(sheet,opts){var val,row,range,header=0,offset=1,r,hdr=[],isempty,R,C,v;var o=opts!=null?opts:{};var raw=o.raw;if(sheet==null||sheet["!ref"]==null)return[];range=o.range!==undefined?o.range:sheet["!ref"];if(o.header===1)header=1;else if(o.header==="A")header=2;else if(Array.isArray(o.header))header=3;switch(typeof range){case"string":r=safe_decode_range(range);break;case"number":r=safe_decode_range(sheet["!ref"]);r.s.r=range;break;default:r=range}if(header>0)offset=0;var rr=encode_row(r.s.r);var cols=new Array(r.e.c-r.s.c+1);var out=new Array(r.e.r-r.s.r-offset+1);var outi=0;for(C=r.s.c;C<=r.e.c;++C){cols[C]=encode_col(C);val=sheet[cols[C]+rr];switch(header){case 1:hdr[C]=C;break;case 2:hdr[C]=cols[C];break;case 3:hdr[C]=o.header[C-r.s.c];break;default:if(val===undefined)continue;hdr[C]=format_cell(val)}}for(R=r.s.r+offset;R<=r.e.r;++R){rr=encode_row(R);isempty=true;row=header===1?[]:Object.create({__rowNum__:R});for(C=r.s.c;C<=r.e.c;++C){val=sheet[cols[C]+rr];if(val===undefined||val.t===undefined)continue;v=val.v;switch(val.t){case"e":continue;case"s":case"str":break;case"b":case"n":break;default:throw"unrecognized type "+val.t}if(v!==undefined){row[hdr[C]]=raw?v:format_cell(val,v);isempty=false}}if(isempty===false)out[outi++]=row}out.length=outi;return out}function sheet_to_row_object_array(sheet,opts){return sheet_to_json(sheet,opts!=null?opts:{})}function sheet_to_csv(sheet,opts){var out="",txt="",qreg=/"/g;var o=opts==null?{}:opts;if(sheet==null||sheet["!ref"]==null)return"";var r=safe_decode_range(sheet["!ref"]);var FS=o.FS!==undefined?o.FS:",",fs=FS.charCodeAt(0);var RS=o.RS!==undefined?o.RS:"\n",rs=RS.charCodeAt(0);var row="",rr="",cols=[];var i=0,cc=0,val;var R=0,C=0;for(C=r.s.c;C<=r.e.c;++C)cols[C]=encode_col(C);for(R=r.s.r;R<=r.e.r;++R){row="";rr=encode_row(R);for(C=r.s.c;C<=r.e.c;++C){val=sheet[cols[C]+rr];txt=val!==undefined?""+format_cell(val):"";for(i=0,cc=0;i!==txt.length;++i)if((cc=txt.charCodeAt(i))===fs||cc===rs||cc===34){txt='"'+txt.replace(qreg,'""')+'"';break}row+=(C===r.s.c?"":FS)+txt}out+=row+RS}return out}var make_csv=sheet_to_csv;function sheet_to_formulae(sheet){var cmds,y="",x,val="";if(sheet==null||sheet["!ref"]==null)return"";var r=safe_decode_range(sheet["!ref"]),rr="",cols=[],C;cmds=new Array((r.e.r-r.s.r+1)*(r.e.c-r.s.c+1));var i=0;for(C=r.s.c;C<=r.e.c;++C)cols[C]=encode_col(C);for(var R=r.s.r;R<=r.e.r;++R){rr=encode_row(R);for(C=r.s.c;C<=r.e.c;++C){y=cols[C]+rr;x=sheet[y];val="";if(x===undefined)continue;if(x.f!=null)val=x.f;else if(x.w!==undefined)val="'"+x.w;else if(x.v===undefined)continue;else val=""+x.v;cmds[i++]=y+"="+val}}cmds.length=i;return cmds}var utils={encode_col:encode_col,encode_row:encode_row,encode_cell:encode_cell,encode_range:encode_range,decode_col:decode_col,decode_row:decode_row,split_cell:split_cell,decode_cell:decode_cell,decode_range:decode_range,format_cell:format_cell,get_formulae:sheet_to_formulae,make_csv:sheet_to_csv,make_json:sheet_to_json,make_formulae:sheet_to_formulae,sheet_to_csv:sheet_to_csv,sheet_to_json:sheet_to_json,sheet_to_formulae:sheet_to_formulae,sheet_to_row_object_array:sheet_to_row_object_array};XLS.parse_xlscfb=parse_xlscfb;XLS.read=xlsread;XLS.readFile=readFile;XLS.utils=utils;XLS.CFB=CFB;XLS.SSF=SSF})(typeof exports!=="undefined"?exports:XLS);
18563 //# sourceMappingURL=dist/xls.min.map
18564 /* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
18565 /* vim: set ts=2: */
18566 /*jshint -W041 */
18567 var XLSX = {};
18568 (function(XLSX){
18569 XLSX.version = '0.7.8';
18570 var current_codepage = 1252, current_cptable;
18571 if(typeof module !== "undefined" && typeof require !== 'undefined') {
18572 if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
18573 current_cptable = cptable[current_codepage];
18574 }
18575 function reset_cp() { set_cp(1252); }
18576 var set_cp = function(cp) { current_codepage = cp; };
18577
18578 function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
18579 var debom_xml = function(data) { return data; };
18580
18581 if(typeof cptable !== 'undefined') {
18582 set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; };
18583 debom_xml = function(data) {
18584 if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
18585 return data;
18586 };
18587 }
18588 /* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
18589 /*jshint -W041 */
18590 var SSF = {};
18591 var make_ssf = function make_ssf(SSF){
18592 SSF.version = '0.8.1';
18593 function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
18594 function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
18595 function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
18596 function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
18597 function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
18598 function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
18599 function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
18600 var p2_32 = Math.pow(2,32);
18601 function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
18602 function isgeneral(s, i) { return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
18603 /* Options */
18604 var opts_fmt = [
18605 ["date1904", 0],
18606 ["output", ""],
18607 ["WTF", false]
18608 ];
18609 function fixopts(o){
18610 for(var y = 0; y != opts_fmt.length; ++y) if(o[opts_fmt[y][0]]===undefined) o[opts_fmt[y][0]]=opts_fmt[y][1];
18611 }
18612 SSF.opts = opts_fmt;
18613 var table_fmt = {
18614 0: 'General',
18615 1: '0',
18616 2: '0.00',
18617 3: '#,##0',
18618 4: '#,##0.00',
18619 9: '0%',
18620 10: '0.00%',
18621 11: '0.00E+00',
18622 12: '# ?/?',
18623 13: '# ??/??',
18624 14: 'm/d/yy',
18625 15: 'd-mmm-yy',
18626 16: 'd-mmm',
18627 17: 'mmm-yy',
18628 18: 'h:mm AM/PM',
18629 19: 'h:mm:ss AM/PM',
18630 20: 'h:mm',
18631 21: 'h:mm:ss',
18632 22: 'm/d/yy h:mm',
18633 37: '#,##0 ;(#,##0)',
18634 38: '#,##0 ;[Red](#,##0)',
18635 39: '#,##0.00;(#,##0.00)',
18636 40: '#,##0.00;[Red](#,##0.00)',
18637 45: 'mm:ss',
18638 46: '[h]:mm:ss',
18639 47: 'mmss.0',
18640 48: '##0.0E+0',
18641 49: '@',
18642 56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
18643 65535: 'General'
18644 };
18645 var days = [
18646 ['Sun', 'Sunday'],
18647 ['Mon', 'Monday'],
18648 ['Tue', 'Tuesday'],
18649 ['Wed', 'Wednesday'],
18650 ['Thu', 'Thursday'],
18651 ['Fri', 'Friday'],
18652 ['Sat', 'Saturday']
18653 ];
18654 var months = [
18655 ['J', 'Jan', 'January'],
18656 ['F', 'Feb', 'February'],
18657 ['M', 'Mar', 'March'],
18658 ['A', 'Apr', 'April'],
18659 ['M', 'May', 'May'],
18660 ['J', 'Jun', 'June'],
18661 ['J', 'Jul', 'July'],
18662 ['A', 'Aug', 'August'],
18663 ['S', 'Sep', 'September'],
18664 ['O', 'Oct', 'October'],
18665 ['N', 'Nov', 'November'],
18666 ['D', 'Dec', 'December']
18667 ];
18668 function frac(x, D, mixed) {
18669 var sgn = x < 0 ? -1 : 1;
18670 var B = x * sgn;
18671 var P_2 = 0, P_1 = 1, P = 0;
18672 var Q_2 = 1, Q_1 = 0, Q = 0;
18673 var A = Math.floor(B);
18674 while(Q_1 < D) {
18675 A = Math.floor(B);
18676 P = A * P_1 + P_2;
18677 Q = A * Q_1 + Q_2;
18678 if((B - A) < 0.0000000005) break;
18679 B = 1 / (B - A);
18680 P_2 = P_1; P_1 = P;
18681 Q_2 = Q_1; Q_1 = Q;
18682 }
18683 if(Q > D) { Q = Q_1; P = P_1; }
18684 if(Q > D) { Q = Q_2; P = P_2; }
18685 if(!mixed) return [0, sgn * P, Q];
18686 if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
18687 var q = Math.floor(sgn * P/Q);
18688 return [q, sgn*P - q*Q, Q];
18689 }
18690 function general_fmt_int(v, opts) { return ""+v; }
18691 SSF._general_int = general_fmt_int;
18692 var general_fmt_num = (function make_general_fmt_num() {
18693 var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
18694 function gfn2(v) {
18695 var w = (v<0?12:11);
18696 var o = gfn5(v.toFixed(12)); if(o.length <= w) return o;
18697 o = v.toPrecision(10); if(o.length <= w) return o;
18698 return v.toExponential(5);
18699 }
18700 function gfn3(v) {
18701 var o = v.toFixed(11).replace(gnr1,".$1");
18702 if(o.length > (v<0?12:11)) o = v.toPrecision(6);
18703 return o;
18704 }
18705 function gfn4(o) {
18706 for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");
18707 return o;
18708 }
18709 function gfn5(o) {
18710 //for(var i = 0; i != o.length; ++i) if(o.charCodeAt(i) === 46) return o.replace(gnr2,"").replace(gnr1,".$1");
18711 //return o;
18712 return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
18713 }
18714 return function general_fmt_num(v, opts) {
18715 var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
18716 if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
18717 else if(Math.abs(V) <= 9) o = gfn2(v);
18718 else if(V === 10) o = v.toFixed(10).substr(0,12);
18719 else o = gfn3(v);
18720 return gfn5(gfn4(o));
18721 };})();
18722 SSF._general_num = general_fmt_num;
18723 function general_fmt(v, opts) {
18724 switch(typeof v) {
18725 case 'string': return v;
18726 case 'boolean': return v ? "TRUE" : "FALSE";
18727 case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
18728 }
18729 throw new Error("unsupported value in General format: " + v);
18730 }
18731 SSF._general = general_fmt;
18732 function fix_hijri(date, o) { return 0; }
18733 function parse_date_code(v,opts,b2) {
18734 if(v > 2958465 || v < 0) return null;
18735 var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
18736 var dout=[];
18737 var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
18738 if(Math.abs(out.u) < 1e-6) out.u = 0;
18739 fixopts(opts != null ? opts : (opts=[]));
18740 if(opts.date1904) date += 1462;
18741 if(out.u > 0.999) {
18742 out.u = 0;
18743 if(++time == 86400) { time = 0; ++date; }
18744 }
18745 if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
18746 else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
18747 else {
18748 if(date > 60) --date;
18749 /* 1 = Jan 1 1900 */
18750 var d = new Date(1900,0,1);
18751 d.setDate(d.getDate() + date - 1);
18752 dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
18753 dow = d.getDay();
18754 if(date < 60) dow = (dow + 6) % 7;
18755 if(b2) dow = fix_hijri(d, dout);
18756 }
18757 out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
18758 out.S = time % 60; time = Math.floor(time / 60);
18759 out.M = time % 60; time = Math.floor(time / 60);
18760 out.H = time;
18761 out.q = dow;
18762 return out;
18763 }
18764 SSF.parse_date_code = parse_date_code;
18765 /*jshint -W086 */
18766 function write_date(type, fmt, val, ss0) {
18767 var o="", ss=0, tt=0, y = val.y, out, outl = 0;
18768 switch(type) {
18769 case 98: /* 'b' buddhist year */
18770 y = val.y + 543;
18771 /* falls through */
18772 case 121: /* 'y' year */
18773 switch(fmt.length) {
18774 case 1: case 2: out = y % 100; outl = 2; break;
18775 default: out = y % 10000; outl = 4; break;
18776 } break;
18777 case 109: /* 'm' month */
18778 switch(fmt.length) {
18779 case 1: case 2: out = val.m; outl = fmt.length; break;
18780 case 3: return months[val.m-1][1];
18781 case 5: return months[val.m-1][0];
18782 default: return months[val.m-1][2];
18783 } break;
18784 case 100: /* 'd' day */
18785 switch(fmt.length) {
18786 case 1: case 2: out = val.d; outl = fmt.length; break;
18787 case 3: return days[val.q][0];
18788 default: return days[val.q][1];
18789 } break;
18790 case 104: /* 'h' 12-hour */
18791 switch(fmt.length) {
18792 case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
18793 default: throw 'bad hour format: ' + fmt;
18794 } break;
18795 case 72: /* 'H' 24-hour */
18796 switch(fmt.length) {
18797 case 1: case 2: out = val.H; outl = fmt.length; break;
18798 default: throw 'bad hour format: ' + fmt;
18799 } break;
18800 case 77: /* 'M' minutes */
18801 switch(fmt.length) {
18802 case 1: case 2: out = val.M; outl = fmt.length; break;
18803 default: throw 'bad minute format: ' + fmt;
18804 } break;
18805 case 115: /* 's' seconds */
18806 if(val.u === 0) switch(fmt) {
18807 case 's': case 'ss': return pad0(val.S, fmt.length);
18808 case '.0': case '.00': case '.000':
18809 }
18810 switch(fmt) {
18811 case 's': case 'ss': case '.0': case '.00': case '.000':
18812 if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
18813 else tt = ss0 === 1 ? 10 : 1;
18814 ss = Math.round((tt)*(val.S + val.u));
18815 if(ss >= 60*tt) ss = 0;
18816 if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
18817 o = pad0(ss,2 + ss0);
18818 if(fmt === 'ss') return o.substr(0,2);
18819 return "." + o.substr(2,fmt.length-1);
18820 default: throw 'bad second format: ' + fmt;
18821 }
18822 case 90: /* 'Z' absolute time */
18823 switch(fmt) {
18824 case '[h]': case '[hh]': out = val.D*24+val.H; break;
18825 case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
18826 case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
18827 default: throw 'bad abstime format: ' + fmt;
18828 } outl = fmt.length === 3 ? 1 : 2; break;
18829 case 101: /* 'e' era */
18830 out = y; outl = 1;
18831 }
18832 if(outl > 0) return pad0(out, outl); else return "";
18833 }
18834 /*jshint +W086 */
18835 function commaify(s) {
18836 if(s.length <= 3) return s;
18837 var j = (s.length % 3), o = s.substr(0,j);
18838 for(; j!=s.length; j+=3) o+=(o.length > 0 ? "," : "") + s.substr(j,3);
18839 return o;
18840 }
18841 var write_num = (function make_write_num(){
18842 var pct1 = /%/g;
18843 function write_num_pct(type, fmt, val){
18844 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
18845 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
18846 }
18847 function write_num_cm(type, fmt, val){
18848 var idx = fmt.length - 1;
18849 while(fmt.charCodeAt(idx-1) === 44) --idx;
18850 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
18851 }
18852 function write_num_exp(fmt, val){
18853 var o;
18854 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
18855 if(fmt.match(/^#+0.0E\+0$/)) {
18856 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
18857 var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
18858 if(ee < 0) ee += period;
18859 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
18860 if(o.indexOf("e") === -1) {
18861 var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
18862 if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
18863 else o += "E+" + (fakee - ee);
18864 while(o.substr(0,2) === "0.") {
18865 o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
18866 o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
18867 }
18868 o = o.replace(/\+-/,"-");
18869 }
18870 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
18871 } else o = val.toExponential(idx);
18872 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
18873 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
18874 return o.replace("e","E");
18875 }
18876 var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
18877 function write_num_f1(r, aval, sign) {
18878 var den = parseInt(r[4]), rr = Math.round(aval * den), base = Math.floor(rr/den);
18879 var myn = (rr - base*den), myd = den;
18880 return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
18881 }
18882 function write_num_f2(r, aval, sign) {
18883 return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
18884 }
18885 var dec1 = /^#*0*\.(0+)/;
18886 var closeparen = /\).*[0#]/;
18887 var phone = /\(###\) ###\\?-####/;
18888 function hashq(str) {
18889 var o = "", cc;
18890 for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
18891 case 35: break;
18892 case 63: o+= " "; break;
18893 case 48: o+= "0"; break;
18894 default: o+= String.fromCharCode(cc);
18895 }
18896 return o;
18897 }
18898 function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
18899 function dec(val, d) { return Math.round((val-Math.floor(val))*Math.pow(10,d)); }
18900 function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
18901 function write_num_flt(type, fmt, val) {
18902 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
18903 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
18904 if(val >= 0) return write_num_flt('n', ffmt, val);
18905 return '(' + write_num_flt('n', ffmt, -val) + ')';
18906 }
18907 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
18908 if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
18909 if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
18910 if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val);
18911 var o, oo;
18912 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
18913 if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
18914 if(fmt.match(/^[#?]+$/)) {
18915 o = pad0r(val,0); if(o === "0") o = "";
18916 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
18917 }
18918 if((r = fmt.match(frac1)) !== null) return write_num_f1(r, aval, sign);
18919 if(fmt.match(/^#+0+$/) !== null) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
18920 if((r = fmt.match(dec1)) !== null) {
18921 o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
18922 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
18923 }
18924 fmt = fmt.replace(/^#+([0.])/, "$1");
18925 if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
18926 return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
18927 }
18928 if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify(pad0r(aval,0));
18929 if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
18930 return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
18931 }
18932 if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
18933 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
18934 o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
18935 ri = 0;
18936 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
18937 }
18938 if(fmt.match(phone) !== null) {
18939 o = write_num_flt(type, "##########", val);
18940 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
18941 }
18942 var oa = "";
18943 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
18944 ri = Math.min(r[4].length,7);
18945 ff = frac(aval, Math.pow(10,ri)-1, false);
18946 o = "" + sign;
18947 oa = write_num("n", r[1], ff[1]);
18948 if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
18949 o += oa + r[2] + "/" + r[3];
18950 oa = rpad_(ff[2],ri);
18951 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
18952 o += oa;
18953 return o;
18954 }
18955 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
18956 ri = Math.min(Math.max(r[1].length, r[4].length),7);
18957 ff = frac(aval, Math.pow(10,ri)-1, true);
18958 return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
18959 }
18960 if((r = fmt.match(/^[#0?]+$/)) !== null) {
18961 o = pad0r(val, 0);
18962 if(fmt.length <= o.length) return o;
18963 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
18964 }
18965 if((r = fmt.match(/^([#0?]+)\.([#0]+)$/)) !== null) {
18966 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
18967 ri = o.indexOf(".");
18968 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
18969 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
18970 }
18971 if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
18972 ri = dec(val, r[1].length);
18973 return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
18974 }
18975 switch(fmt) {
18976 case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
18977 default:
18978 }
18979 throw new Error("unsupported format |" + fmt + "|");
18980 }
18981 function write_num_cm2(type, fmt, val){
18982 var idx = fmt.length - 1;
18983 while(fmt.charCodeAt(idx-1) === 44) --idx;
18984 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
18985 }
18986 function write_num_pct2(type, fmt, val){
18987 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
18988 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
18989 }
18990 function write_num_exp2(fmt, val){
18991 var o;
18992 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
18993 if(fmt.match(/^#+0.0E\+0$/)) {
18994 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
18995 var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
18996 if(ee < 0) ee += period;
18997 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
18998 if(!o.match(/[Ee]/)) {
18999 var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
19000 if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
19001 else o += "E+" + (fakee - ee);
19002 o = o.replace(/\+-/,"-");
19003 }
19004 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
19005 } else o = val.toExponential(idx);
19006 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
19007 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
19008 return o.replace("e","E");
19009 }
19010 function write_num_int(type, fmt, val) {
19011 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
19012 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
19013 if(val >= 0) return write_num_int('n', ffmt, val);
19014 return '(' + write_num_int('n', ffmt, -val) + ')';
19015 }
19016 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
19017 if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
19018 if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
19019 if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val);
19020 var o;
19021 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
19022 if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
19023 if(fmt.match(/^[#?]+$/)) {
19024 o = (""+val); if(val === 0) o = "";
19025 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
19026 }
19027 if((r = fmt.match(frac1)) !== null) return write_num_f2(r, aval, sign);
19028 if(fmt.match(/^#+0+$/) !== null) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
19029 if((r = fmt.match(dec1)) !== null) {
19030 o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
19031 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
19032 }
19033 fmt = fmt.replace(/^#+([0.])/, "$1");
19034 if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
19035 return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
19036 }
19037 if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify((""+aval));
19038 if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
19039 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
19040 }
19041 if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
19042 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
19043 o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
19044 ri = 0;
19045 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
19046 }
19047 if(fmt.match(phone) !== null) {
19048 o = write_num_int(type, "##########", val);
19049 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
19050 }
19051 var oa = "";
19052 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
19053 ri = Math.min(r[4].length,7);
19054 ff = frac(aval, Math.pow(10,ri)-1, false);
19055 o = "" + sign;
19056 oa = write_num("n", r[1], ff[1]);
19057 if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
19058 o += oa + r[2] + "/" + r[3];
19059 oa = rpad_(ff[2],ri);
19060 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
19061 o += oa;
19062 return o;
19063 }
19064 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
19065 ri = Math.min(Math.max(r[1].length, r[4].length),7);
19066 ff = frac(aval, Math.pow(10,ri)-1, true);
19067 return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
19068 }
19069 if((r = fmt.match(/^[#0?]+$/)) !== null) {
19070 o = "" + val;
19071 if(fmt.length <= o.length) return o;
19072 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
19073 }
19074 if((r = fmt.match(/^([#0]+)\.([#0]+)$/)) !== null) {
19075 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
19076 ri = o.indexOf(".");
19077 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
19078 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
19079 }
19080 if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
19081 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
19082 }
19083 switch(fmt) {
19084 case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
19085 default:
19086 }
19087 throw new Error("unsupported format |" + fmt + "|");
19088 }
19089 return function write_num(type, fmt, val) {
19090 return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
19091 };})();
19092 function split_fmt(fmt) {
19093 var out = [];
19094 var in_str = false, cc;
19095 for(var i = 0, j = 0; i < fmt.length; ++i) switch((cc=fmt.charCodeAt(i))) {
19096 case 34: /* '"' */
19097 in_str = !in_str; break;
19098 case 95: case 42: case 92: /* '_' '*' '\\' */
19099 ++i; break;
19100 case 59: /* ';' */
19101 out[out.length] = fmt.substr(j,i-j);
19102 j = i+1;
19103 }
19104 out[out.length] = fmt.substr(j);
19105 if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
19106 return out;
19107 }
19108 SSF._split = split_fmt;
19109 var abstime = /\[[HhMmSs]*\]/;
19110 function eval_fmt(fmt, v, opts, flen) {
19111 var out = [], o = "", i = 0, c = "", lst='t', q, dt, j, cc;
19112 var hr='H';
19113 /* Tokenize */
19114 while(i < fmt.length) {
19115 switch((c = fmt[i])) {
19116 case 'G': /* General */
19117 if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
19118 out[out.length] = {t:'G', v:'General'}; i+=7; break;
19119 case '"': /* Literal text */
19120 for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
19121 out[out.length] = {t:'t', v:o}; ++i; break;
19122 case '\\': var w = fmt[++i], t = (w === "(" || w === ")") ? w : 't';
19123 out[out.length] = {t:t, v:w}; ++i; break;
19124 case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
19125 case '@': /* Text Placeholder */
19126 out[out.length] = {t:'T', v:v}; ++i; break;
19127 case 'B': case 'b':
19128 if(fmt[i+1] === "1" || fmt[i+1] === "2") {
19129 if(dt==null) { dt=parse_date_code(v, opts, fmt[i+1] === "2"); if(dt==null) return ""; }
19130 out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
19131 }
19132 /* falls through */
19133 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
19134 c = c.toLowerCase();
19135 /* falls through */
19136 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
19137 if(v < 0) return "";
19138 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
19139 o = c; while(++i<fmt.length && fmt[i].toLowerCase() === c) o+=c;
19140 if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
19141 if(c === 'h') c = hr;
19142 out[out.length] = {t:c, v:o}; lst = c; break;
19143 case 'A':
19144 q={t:c, v:"A"};
19145 if(dt==null) dt=parse_date_code(v, opts);
19146 if(fmt.substr(i, 3) === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
19147 else if(fmt.substr(i,5) === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
19148 else { q.t = "t"; ++i; }
19149 if(dt==null && q.t === 'T') return "";
19150 out[out.length] = q; lst = c; break;
19151 case '[':
19152 o = c;
19153 while(fmt[i++] !== ']' && i < fmt.length) o += fmt[i];
19154 if(o.substr(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
19155 if(o.match(abstime)) {
19156 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
19157 out[out.length] = {t:'Z', v:o.toLowerCase()};
19158 } else { o=""; }
19159 break;
19160 /* Numbers */
19161 case '.':
19162 if(dt != null) {
19163 o = c; while((c=fmt[++i]) === "0") o += c;
19164 out[out.length] = {t:'s', v:o}; break;
19165 }
19166 /* falls through */
19167 case '0': case '#':
19168 o = c; while("0#?.,E+-%".indexOf(c=fmt[++i]) > -1 || c=='\\' && fmt[i+1] == "-" && "0#".indexOf(fmt[i+2])>-1) o += c;
19169 out[out.length] = {t:'n', v:o}; break;
19170 case '?':
19171 o = c; while(fmt[++i] === c) o+=c;
19172 q={t:c, v:o}; out[out.length] = q; lst = c; break;
19173 case '*': ++i; if(fmt[i] == ' ' || fmt[i] == '*') ++i; break; // **
19174 case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
19175 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
19176 o = c; while("0123456789".indexOf(fmt[++i]) > -1) o+=fmt[i];
19177 out[out.length] = {t:'D', v:o}; break;
19178 case ' ': out[out.length] = {t:c, v:c}; ++i; break;
19179 default:
19180 if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxz".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
19181 out[out.length] = {t:'t', v:c}; ++i; break;
19182 }
19183 }
19184 var bt = 0, ss0 = 0, ssm;
19185 for(i=out.length-1, lst='t'; i >= 0; --i) {
19186 switch(out[i].t) {
19187 case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
19188 case 's':
19189 if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
19190 if(bt < 3) bt = 3;
19191 /* falls through */
19192 case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
19193 case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
19194 case 'X': if(out[i].v === "B2");
19195 break;
19196 case 'Z':
19197 if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
19198 if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
19199 if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
19200 }
19201 }
19202 switch(bt) {
19203 case 0: break;
19204 case 1:
19205 if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
19206 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
19207 if(dt.M >= 60) { dt.M = 0; ++dt.H; }
19208 break;
19209 case 2:
19210 if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
19211 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
19212 break;
19213 }
19214 /* replace fields */
19215 var nstr = "", jj;
19216 for(i=0; i < out.length; ++i) {
19217 switch(out[i].t) {
19218 case 't': case 'T': case ' ': case 'D': break;
19219 case 'X': out[i] = undefined; break;
19220 case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
19221 out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
19222 out[i].t = 't'; break;
19223 case 'n': case '(': case '?':
19224 jj = i+1;
19225 while(out[jj] != null && (
19226 (c=out[jj].t) === "?" || c === "D" ||
19227 (c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
19228 out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
19229 c === 't' && (out[jj].v === '/' || '$€'.indexOf(out[jj].v) > -1 || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
19230 )) {
19231 out[i].v += out[jj].v;
19232 out[jj] = undefined; ++jj;
19233 }
19234 nstr += out[i].v;
19235 i = jj-1; break;
19236 case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
19237 }
19238 }
19239 var vv = "", myv, ostr;
19240 if(nstr.length > 0) {
19241 myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); /* '-' */
19242 ostr = write_num(nstr.charCodeAt(0) === 40 ? '(' : 'n', nstr, myv); /* '(' */
19243 jj=ostr.length-1;
19244 var decpt = out.length;
19245 for(i=0; i < out.length; ++i) if(out[i] != null && out[i].v.indexOf(".") > -1) { decpt = i; break; }
19246 var lasti=out.length;
19247 if(decpt === out.length && ostr.indexOf("E") === -1) {
19248 for(i=out.length-1; i>= 0;--i) {
19249 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
19250 if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
19251 else if(jj < 0) out[i].v = "";
19252 else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
19253 out[i].t = 't';
19254 lasti = i;
19255 }
19256 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
19257 }
19258 else if(decpt !== out.length && ostr.indexOf("E") === -1) {
19259 jj = ostr.indexOf(".")-1;
19260 for(i=decpt; i>= 0; --i) {
19261 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
19262 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
19263 vv = out[i].v.substr(j+1);
19264 for(; j>=0; --j) {
19265 if(jj>=0 && (out[i].v[j] === "0" || out[i].v[j] === "#")) vv = ostr[jj--] + vv;
19266 }
19267 out[i].v = vv;
19268 out[i].t = 't';
19269 lasti = i;
19270 }
19271 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
19272 jj = ostr.indexOf(".")+1;
19273 for(i=decpt; i<out.length; ++i) {
19274 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1 && i !== decpt ) continue;
19275 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
19276 vv = out[i].v.substr(0,j);
19277 for(; j<out[i].v.length; ++j) {
19278 if(jj<ostr.length) vv += ostr[jj++];
19279 }
19280 out[i].v = vv;
19281 out[i].t = 't';
19282 lasti = i;
19283 }
19284 }
19285 }
19286 for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
19287 myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
19288 out[i].v = write_num(out[i].t, out[i].v, myv);
19289 out[i].t = 't';
19290 }
19291 var retval = "";
19292 for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
19293 return retval;
19294 }
19295 SSF._eval = eval_fmt;
19296 var cfregex = /\[[=<>]/;
19297 var cfregex2 = /\[([=<>]*)(-?\d+\.?\d*)\]/;
19298 function chkcond(v, rr) {
19299 if(rr == null) return false;
19300 var thresh = parseFloat(rr[2]);
19301 switch(rr[1]) {
19302 case "=": if(v == thresh) return true; break;
19303 case ">": if(v > thresh) return true; break;
19304 case "<": if(v < thresh) return true; break;
19305 case "<>": if(v != thresh) return true; break;
19306 case ">=": if(v >= thresh) return true; break;
19307 case "<=": if(v <= thresh) return true; break;
19308 }
19309 return false;
19310 }
19311 function choose_fmt(f, v) {
19312 var fmt = split_fmt(f);
19313 var l = fmt.length, lat = fmt[l-1].indexOf("@");
19314 if(l<4 && lat>-1) --l;
19315 if(fmt.length > 4) throw "cannot find right format for |" + fmt + "|";
19316 if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
19317 switch(fmt.length) {
19318 case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
19319 case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
19320 case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
19321 case 4: break;
19322 }
19323 var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
19324 if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
19325 if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
19326 var m1 = fmt[0].match(cfregex2);
19327 var m2 = fmt[1].match(cfregex2);
19328 return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
19329 }
19330 return [l, ff];
19331 }
19332 function format(fmt,v,o) {
19333 fixopts(o != null ? o : (o=[]));
19334 var sfmt = "";
19335 switch(typeof fmt) {
19336 case "string": sfmt = fmt; break;
19337 case "number": sfmt = (o.table != null ? o.table : table_fmt)[fmt]; break;
19338 }
19339 if(isgeneral(sfmt,0)) return general_fmt(v, o);
19340 var f = choose_fmt(sfmt, v);
19341 if(isgeneral(f[1])) return general_fmt(v, o);
19342 if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
19343 else if(v === "" || v == null) return "";
19344 return eval_fmt(f[1], v, o, f[0]);
19345 }
19346 SSF._table = table_fmt;
19347 SSF.load = function load_entry(fmt, idx) { table_fmt[idx] = fmt; };
19348 SSF.format = format;
19349 SSF.get_table = function get_table() { return table_fmt; };
19350 SSF.load_table = function load_table(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i] !== undefined) SSF.load(tbl[i], i); };
19351 };
19352 make_ssf(SSF);
19353 function isval(x) { return x !== undefined && x !== null; }
19354
19355 function keys(o) { return Object.keys(o); }
19356
19357 function evert_key(obj, key) {
19358 var o = [], K = keys(obj);
19359 for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
19360 return o;
19361 }
19362
19363 function evert(obj) {
19364 var o = [], K = keys(obj);
19365 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
19366 return o;
19367 }
19368
19369 function evert_num(obj) {
19370 var o = [], K = keys(obj);
19371 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
19372 return o;
19373 }
19374
19375 function evert_arr(obj) {
19376 var o = [], K = keys(obj);
19377 for(var i = 0; i !== K.length; ++i) {
19378 if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
19379 o[obj[K[i]]].push(K[i]);
19380 }
19381 return o;
19382 }
19383
19384 /* TODO: date1904 logic */
19385 function datenum(v, date1904) {
19386 if(date1904) v+=1462;
19387 var epoch = Date.parse(v);
19388 return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
19389 }
19390
19391 function cc2str(arr) {
19392 var o = "";
19393 for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
19394 return o;
19395 }
19396
19397 var has_buf = (typeof Buffer !== 'undefined');
19398 function getdata(data) {
19399 if(!data) return null;
19400 if(data.name.substr(-4) === ".bin") {
19401 if(data.data) return char_codes(data.data);
19402 if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
19403 if(data._data && data._data.getContent) return Array.prototype.slice.call(data._data.getContent());
19404 } else {
19405 if(data.data) return data.name.substr(-4) !== ".bin" ? debom_xml(data.data) : char_codes(data.data);
19406 if(data.asNodeBuffer && has_buf) return debom_xml(data.asNodeBuffer().toString('binary'));
19407 if(data.asBinary) return debom_xml(data.asBinary());
19408 if(data._data && data._data.getContent) return debom_xml(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
19409 }
19410 return null;
19411 }
19412
19413 function getzipfile(zip, file) {
19414 var f = file; if(zip.files[f]) return zip.files[f];
19415 f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
19416 f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
19417 throw new Error("Cannot find file " + file + " in zip");
19418 }
19419
19420 function getzipdata(zip, file, safe) {
19421 if(!safe) return getdata(getzipfile(zip, file));
19422 if(!file) return null;
19423 try { return getzipdata(zip, file); } catch(e) { return null; }
19424 }
19425
19426 var _fs, jszip;
19427 if(typeof JSZip !== 'undefined') jszip = JSZip;
19428 if (typeof exports !== 'undefined') {
19429 if (typeof module !== 'undefined' && module.exports) {
19430 if(has_buf && typeof jszip === 'undefined') jszip = require('js'+'zip');
19431 if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
19432 _fs = require('f'+'s');
19433 }
19434 }
19435 var attregexg=/\b[\w:]+=["'][^"]*['"]/g;
19436 var tagregex=/<[^>]*>/g;
19437 var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
19438 function parsexmltag(tag, skip_root) {
19439 var z = [];
19440 var eq = 0, c = 0;
19441 for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
19442 if(!skip_root) z[0] = tag.substr(0, eq);
19443 if(eq === tag.length) return z;
19444 var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
19445 if(m) for(i = 0; i != m.length; ++i) {
19446 cc = m[i];
19447 for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
19448 q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
19449 for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
19450 if(j===q.length) z[q] = v;
19451 else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
19452 }
19453 return z;
19454 }
19455 function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
19456
19457 var encodings = {
19458 '&quot;': '"',
19459 '&apos;': "'",
19460 '&gt;': '>',
19461 '&lt;': '<',
19462 '&amp;': '&'
19463 };
19464 var rencoding = evert(encodings);
19465 var rencstr = "&<>'\"".split("");
19466
19467 // TODO: CP remap (need to read file version to determine OS)
19468 var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
19469 function unescapexml(text){
19470 var s = text + '';
19471 return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
19472 }
19473 var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
19474 function escapexml(text){
19475 var s = text + '';
19476 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
19477 }
19478
19479 function parsexmlbool(value, tag) {
19480 switch(value) {
19481 case '1': case 'true': case 'TRUE': return true;
19482 /* case '0': case 'false': case 'FALSE':*/
19483 default: return false;
19484 }
19485 }
19486
19487 var utf8read = function utf8reada(orig) {
19488 var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
19489 while (i < orig.length) {
19490 c = orig.charCodeAt(i++);
19491 if (c < 128) { out += String.fromCharCode(c); continue; }
19492 d = orig.charCodeAt(i++);
19493 if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
19494 e = orig.charCodeAt(i++);
19495 if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
19496 f = orig.charCodeAt(i++);
19497 w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
19498 out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
19499 out += String.fromCharCode(0xDC00 + (w&1023));
19500 }
19501 return out;
19502 };
19503
19504
19505 if(has_buf) {
19506 var utf8readb = function utf8readb(data) {
19507 var out = new Buffer(2*data.length), w, i, j = 1, k = 0, ww=0, c;
19508 for(i = 0; i < data.length; i+=j) {
19509 j = 1;
19510 if((c=data.charCodeAt(i)) < 128) w = c;
19511 else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
19512 else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
19513 else { j = 4;
19514 w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
19515 w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
19516 }
19517 if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
19518 out[k++] = w%256; out[k++] = w>>>8;
19519 }
19520 out.length = k;
19521 return out.toString('ucs2');
19522 };
19523 var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
19524 if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
19525 var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
19526 if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
19527 }
19528
19529 // matches <foo>...</foo> extracts content
19530 var matchtag = (function() {
19531 var mtcache = {};
19532 return function matchtag(f,g) {
19533 var t = f+"|"+g;
19534 if(mtcache[t] !== undefined) return mtcache[t];
19535 return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',(g||"")));
19536 };
19537 })();
19538
19539 var vtregex = (function(){ var vt_cache = {};
19540 return function vt_regex(bt) {
19541 if(vt_cache[bt] !== undefined) return vt_cache[bt];
19542 return (vt_cache[bt] = new RegExp("<vt:" + bt + ">(.*?)</vt:" + bt + ">", 'g') );
19543 };})();
19544 var vtvregex = /<\/?vt:variant>/g, vtmregex = /<vt:([^>]*)>(.*)</;
19545 function parseVector(data) {
19546 var h = parsexmltag(data);
19547
19548 var matches = data.match(vtregex(h.baseType))||[];
19549 if(matches.length != h.size) throw "unexpected vector length " + matches.length + " != " + h.size;
19550 var res = [];
19551 matches.forEach(function(x) {
19552 var v = x.replace(vtvregex,"").match(vtmregex);
19553 res.push({v:v[2], t:v[1]});
19554 });
19555 return res;
19556 }
19557
19558 var wtregex = /(^\s|\s$|\n)/;
19559 function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
19560
19561 function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
19562 function writextag(f,g,h) { return '<' + f + (isval(h) ? wxt_helper(h) : "") + (isval(g) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
19563
19564 function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
19565
19566 function write_vt(s) {
19567 switch(typeof s) {
19568 case 'string': return writextag('vt:lpwstr', s);
19569 case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
19570 case 'boolean': return writextag('vt:bool',s?'true':'false');
19571 }
19572 if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
19573 throw new Error("Unable to serialize " + s);
19574 }
19575
19576 var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
19577 var XMLNS = {
19578 'dc': 'http://purl.org/dc/elements/1.1/',
19579 'dcterms': 'http://purl.org/dc/terms/',
19580 'dcmitype': 'http://purl.org/dc/dcmitype/',
19581 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
19582 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
19583 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
19584 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
19585 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
19586 'xsd': 'http://www.w3.org/2001/XMLSchema'
19587 };
19588
19589 XMLNS.main = [
19590 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
19591 'http://purl.oclc.org/ooxml/spreadsheetml/main',
19592 'http://schemas.microsoft.com/office/excel/2006/main',
19593 'http://schemas.microsoft.com/office/excel/2006/2'
19594 ];
19595 function readIEEE754(buf, idx, isLE, nl, ml) {
19596 if(isLE === undefined) isLE = true;
19597 if(!nl) nl = 8;
19598 if(!ml && nl === 8) ml = 52;
19599 var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1;
19600 var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i];
19601
19602 i += d;
19603 e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el;
19604 for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8);
19605 m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml;
19606 for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8);
19607 if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity);
19608 else if (e === 0) e = 1 - eBias;
19609 else { m = m + Math.pow(2, ml); e = e - eBias; }
19610 return (s ? -1 : 1) * m * Math.pow(2, e - ml);
19611 }
19612
19613 var __toBuffer, ___toBuffer;
19614 __toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
19615 var __double, ___double;
19616 __double = ___double = function(b, idx) { return readIEEE754(b, idx);};
19617
19618 var is_buf = function is_buf_a(a) { return Array.isArray(a); };
19619 if(has_buf) {
19620 __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
19621 __double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
19622 is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
19623 }
19624
19625
19626 var __readUInt8 = function(b, idx) { return b[idx]; };
19627 var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
19628 var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
19629 var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
19630 var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
19631
19632
19633 function ReadShift(size, t) {
19634 var o="", oo=[], w, vv, i, loc;
19635 if(t === 'dbcs') {
19636 loc = this.l;
19637 if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
19638 else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
19639 size *= 2;
19640 } else switch(size) {
19641 case 1: o = __readUInt8(this, this.l); break;
19642 case 2: o = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); break;
19643 case 4: o = __readUInt32LE(this, this.l); break;
19644 case 8: if(t === 'f') { o = __double(this, this.l); break; }
19645 }
19646 this.l+=size; return o;
19647 }
19648
19649 function WriteShift(t, val, f) {
19650 var size, i;
19651 if(f === 'dbcs') {
19652 for(i = 0; i != val.length; ++i) this.writeUInt16LE(val.charCodeAt(i), this.l + 2 * i);
19653 size = 2 * val.length;
19654 } else switch(t) {
19655 case 1: size = 1; this[this.l] = val&255; break;
19656 case 3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break;
19657 case 4: size = 4; this.writeUInt32LE(val, this.l); break;
19658 case 8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
19659 /* falls through */
19660 case 16: break;
19661 case -4: size = 4; this.writeInt32LE(val, this.l); break;
19662 }
19663 this.l += size; return this;
19664 }
19665
19666 function prep_blob(blob, pos) {
19667 blob.l = pos;
19668 blob.read_shift = ReadShift;
19669 blob.write_shift = WriteShift;
19670 }
19671
19672 function parsenoop(blob, length) { blob.l += length; }
19673
19674 function writenoop(blob, length) { blob.l += length; }
19675
19676 function new_buf(sz) {
19677 var o = has_buf ? new Buffer(sz) : new Array(sz);
19678 prep_blob(o, 0);
19679 return o;
19680 }
19681
19682 /* [MS-XLSB] 2.1.4 Record */
19683 function recordhopper(data, cb, opts) {
19684 var tmpbyte, cntbyte, length;
19685 prep_blob(data, data.l || 0);
19686 while(data.l < data.length) {
19687 var RT = data.read_shift(1);
19688 if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
19689 var R = RecordEnum[RT] || RecordEnum[0xFFFF];
19690 tmpbyte = data.read_shift(1);
19691 length = tmpbyte & 0x7F;
19692 for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
19693 var d = R.f(data, length, opts);
19694 if(cb(d, R, RT)) return;
19695 }
19696 }
19697
19698 /* control buffer usage for fixed-length buffers */
19699 function buf_array() {
19700 var bufs = [], blksz = 2048;
19701 var newblk = function ba_newblk(sz) {
19702 var o = new_buf(sz);
19703 prep_blob(o, 0);
19704 return o;
19705 };
19706
19707 var curbuf = newblk(blksz);
19708
19709 var endbuf = function ba_endbuf() {
19710 curbuf.length = curbuf.l;
19711 if(curbuf.length > 0) bufs.push(curbuf);
19712 curbuf = null;
19713 };
19714
19715 var next = function ba_next(sz) {
19716 if(sz < curbuf.length - curbuf.l) return curbuf;
19717 endbuf();
19718 return (curbuf = newblk(Math.max(sz+1, blksz)));
19719 };
19720
19721 var end = function ba_end() {
19722 endbuf();
19723 return __toBuffer([bufs]);
19724 };
19725
19726 var push = function ba_push(buf) { endbuf(); curbuf = buf; next(blksz); };
19727
19728 return { next:next, push:push, end:end, _bufs:bufs };
19729 }
19730
19731 function write_record(ba, type, payload, length) {
19732 var t = evert_RE[type], l;
19733 if(!length) length = RecordEnum[t].p || (payload||[]).length || 0;
19734 l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
19735 if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
19736 var o = ba.next(l);
19737 if(t <= 0x7F) o.write_shift(1, t);
19738 else {
19739 o.write_shift(1, (t & 0x7F) + 0x80);
19740 o.write_shift(1, (t >> 7));
19741 }
19742 for(var i = 0; i != 4; ++i) {
19743 if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
19744 else { o.write_shift(1, length); break; }
19745 }
19746 if(length > 0 && is_buf(payload)) ba.push(payload);
19747 }
19748
19749 /* [MS-XLSB] 2.5.143 */
19750 function parse_StrRun(data, length) {
19751 return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
19752 }
19753
19754 /* [MS-XLSB] 2.1.7.121 */
19755 function parse_RichStr(data, length) {
19756 var start = data.l;
19757 var flags = data.read_shift(1);
19758 var str = parse_XLWideString(data);
19759 var rgsStrRun = [];
19760 var z = { t: str, h: str };
19761 if((flags & 1) !== 0) { /* fRichStr */
19762 /* TODO: formatted string */
19763 var dwSizeStrRun = data.read_shift(4);
19764 for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
19765 z.r = rgsStrRun;
19766 }
19767 else z.r = "<t>" + escapexml(str) + "</t>";
19768 if((flags & 2) !== 0) { /* fExtStr */
19769 /* TODO: phonetic string */
19770 }
19771 data.l = start + length;
19772 return z;
19773 }
19774 function write_RichStr(str, o) {
19775 /* TODO: formatted string */
19776 if(o == null) o = new_buf(5+2*str.t.length);
19777 o.write_shift(1,0);
19778 write_XLWideString(str.t, o);
19779 return o;
19780 }
19781
19782 /* [MS-XLSB] 2.5.9 */
19783 function parse_Cell(data) {
19784 var col = data.read_shift(4);
19785 var iStyleRef = data.read_shift(2);
19786 iStyleRef += data.read_shift(1) <<16;
19787 var fPhShow = data.read_shift(1);
19788 return { c:col, iStyleRef: iStyleRef };
19789 }
19790 function write_Cell(cell, o) {
19791 if(o == null) o = new_buf(8);
19792 o.write_shift(-4, cell.c);
19793 o.write_shift(3, cell.iStyleRef === undefined ? cell.iStyleRef : cell.s);
19794 o.write_shift(1, 0); /* fPhShow */
19795 return o;
19796 }
19797
19798
19799 /* [MS-XLSB] 2.5.21 */
19800 function parse_CodeName (data, length) { return parse_XLWideString(data, length); }
19801
19802 /* [MS-XLSB] 2.5.166 */
19803 function parse_XLNullableWideString(data) {
19804 var cchCharacters = data.read_shift(4);
19805 return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
19806 }
19807 function write_XLNullableWideString(data, o) {
19808 if(!o) o = new_buf(127);
19809 o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
19810 if(data.length > 0) o.write_shift(0, data, 'dbcs');
19811 return o;
19812 }
19813
19814 /* [MS-XLSB] 2.5.168 */
19815 function parse_XLWideString(data) {
19816 var cchCharacters = data.read_shift(4);
19817 return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
19818 }
19819 function write_XLWideString(data, o) {
19820 if(o == null) o = new_buf(4+2*data.length);
19821 o.write_shift(4, data.length);
19822 if(data.length > 0) o.write_shift(0, data, 'dbcs');
19823 return o;
19824 }
19825
19826 /* [MS-XLSB] 2.5.114 */
19827 var parse_RelID = parse_XLNullableWideString;
19828 var write_RelID = write_XLNullableWideString;
19829
19830
19831 /* [MS-XLSB] 2.5.122 */
19832 function parse_RkNumber(data) {
19833 var b = data.slice(data.l, data.l+4);
19834 var fX100 = b[0] & 1, fInt = b[0] & 2;
19835 data.l+=4;
19836 b[0] &= 0xFC;
19837 var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
19838 return fX100 ? RK/100 : RK;
19839 }
19840
19841 /* [MS-XLSB] 2.5.153 */
19842 function parse_UncheckedRfX(data) {
19843 var cell = {s: {}, e: {}};
19844 cell.s.r = data.read_shift(4);
19845 cell.e.r = data.read_shift(4);
19846 cell.s.c = data.read_shift(4);
19847 cell.e.c = data.read_shift(4);
19848 return cell;
19849 }
19850
19851 function write_UncheckedRfX(r, o) {
19852 if(!o) o = new_buf(16);
19853 o.write_shift(4, r.s.r);
19854 o.write_shift(4, r.e.r);
19855 o.write_shift(4, r.s.c);
19856 o.write_shift(4, r.e.c);
19857 return o;
19858 }
19859
19860 /* [MS-XLSB] 2.5.171 */
19861 function parse_Xnum(data, length) { return data.read_shift(8, 'f'); }
19862 function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); }
19863
19864 /* [MS-XLSB] 2.5.198.2 */
19865 var BErr = {
19866 0x00: "#NULL!",
19867 0x07: "#DIV/0!",
19868 0x0F: "#VALUE!",
19869 0x17: "#REF!",
19870 0x1D: "#NAME?",
19871 0x24: "#NUM!",
19872 0x2A: "#N/A",
19873 0x2B: "#GETTING_DATA",
19874 0xFF: "#WTF?"
19875 };
19876 var RBErr = evert_num(BErr);
19877
19878 /* [MS-XLSB] 2.4.321 BrtColor */
19879 function parse_BrtColor(data, length) {
19880 var out = {};
19881 var d = data.read_shift(1);
19882 out.fValidRGB = d & 1;
19883 out.xColorType = d >>> 1;
19884 out.index = data.read_shift(1);
19885 out.nTintAndShade = data.read_shift(2, 'i');
19886 out.bRed = data.read_shift(1);
19887 out.bGreen = data.read_shift(1);
19888 out.bBlue = data.read_shift(1);
19889 out.bAlpha = data.read_shift(1);
19890 }
19891
19892 /* [MS-XLSB] 2.5.52 */
19893 function parse_FontFlags(data, length) {
19894 var d = data.read_shift(1);
19895 data.l++;
19896 var out = {
19897 fItalic: d & 0x2,
19898 fStrikeout: d & 0x8,
19899 fOutline: d & 0x10,
19900 fShadow: d & 0x20,
19901 fCondense: d & 0x40,
19902 fExtend: d & 0x80
19903 };
19904 return out;
19905 }
19906 /* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
19907 /* 12.3 Part Summary <SpreadsheetML> */
19908 /* 14.2 Part Summary <DrawingML> */
19909 /* [MS-XLSX] 2.1 Part Enumerations */
19910 /* [MS-XLSB] 2.1.7 Part Enumeration */
19911 var ct2type = {
19912 /* Workbook */
19913 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
19914
19915 /* Worksheet */
19916 "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
19917
19918 /* Chartsheet */
19919 "application/vnd.ms-excel.chartsheet": "TODO",
19920 "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "TODO",
19921
19922 /* Dialogsheet */
19923 "application/vnd.ms-excel.dialogsheet": "TODO",
19924 "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "TODO",
19925
19926 /* Macrosheet */
19927 "application/vnd.ms-excel.macrosheet": "TODO",
19928 "application/vnd.ms-excel.macrosheet+xml": "TODO",
19929 "application/vnd.ms-excel.intlmacrosheet": "TODO",
19930 "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
19931
19932 /* File Properties */
19933 "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
19934 "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
19935 "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
19936
19937 /* Custom Data Properties */
19938 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
19939
19940 /* Comments */
19941 "application/vnd.ms-excel.comments": "comments",
19942 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments",
19943
19944 /* PivotTable */
19945 "application/vnd.ms-excel.pivotTable": "TODO",
19946 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
19947
19948 /* Calculation Chain */
19949 "application/vnd.ms-excel.calcChain": "calcchains",
19950 "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
19951
19952 /* Printer Settings */
19953 "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
19954
19955 /* ActiveX */
19956 "application/vnd.ms-office.activeX": "TODO",
19957 "application/vnd.ms-office.activeX+xml": "TODO",
19958
19959 /* Custom Toolbars */
19960 "application/vnd.ms-excel.attachedToolbars": "TODO",
19961
19962 /* External Data Connections */
19963 "application/vnd.ms-excel.connections": "TODO",
19964 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
19965
19966 /* External Links */
19967 "application/vnd.ms-excel.externalLink": "TODO",
19968 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "TODO",
19969
19970 /* Metadata */
19971 "application/vnd.ms-excel.sheetMetadata": "TODO",
19972 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
19973
19974 /* PivotCache */
19975 "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
19976 "application/vnd.ms-excel.pivotCacheRecords": "TODO",
19977 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
19978 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
19979
19980 /* Query Table */
19981 "application/vnd.ms-excel.queryTable": "TODO",
19982 "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
19983
19984 /* Shared Workbook */
19985 "application/vnd.ms-excel.userNames": "TODO",
19986 "application/vnd.ms-excel.revisionHeaders": "TODO",
19987 "application/vnd.ms-excel.revisionLog": "TODO",
19988 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
19989 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
19990 "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
19991
19992 /* Single Cell Table */
19993 "application/vnd.ms-excel.tableSingleCells": "TODO",
19994 "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
19995
19996 /* Slicer */
19997 "application/vnd.ms-excel.slicer": "TODO",
19998 "application/vnd.ms-excel.slicerCache": "TODO",
19999 "application/vnd.ms-excel.slicer+xml": "TODO",
20000 "application/vnd.ms-excel.slicerCache+xml": "TODO",
20001
20002 /* Sort Map */
20003 "application/vnd.ms-excel.wsSortMap": "TODO",
20004
20005 /* Table */
20006 "application/vnd.ms-excel.table": "TODO",
20007 "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
20008
20009 /* Themes */
20010 "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
20011
20012 /* Timeline */
20013 "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
20014 "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
20015
20016 /* VBA */
20017 "application/vnd.ms-office.vbaProject": "vba",
20018 "application/vnd.ms-office.vbaProjectSignature": "vba",
20019
20020 /* Volatile Dependencies */
20021 "application/vnd.ms-office.volatileDependencies": "TODO",
20022 "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
20023
20024 /* Control Properties */
20025 "application/vnd.ms-excel.controlproperties+xml": "TODO",
20026
20027 /* Data Model */
20028 "application/vnd.openxmlformats-officedocument.model+data": "TODO",
20029
20030 /* Survey */
20031 "application/vnd.ms-excel.Survey+xml": "TODO",
20032
20033 /* Drawing */
20034 "application/vnd.openxmlformats-officedocument.drawing+xml": "TODO",
20035 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
20036 "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
20037 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
20038 "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
20039 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
20040 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
20041
20042 /* VML */
20043 "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
20044
20045 "application/vnd.openxmlformats-package.relationships+xml": "rels",
20046 "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
20047
20048 "sheet": "js"
20049 };
20050
20051 var CT_LIST = (function(){
20052 var o = {
20053 workbooks: {
20054 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
20055 xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
20056 xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
20057 xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
20058 },
20059 strs: { /* Shared Strings */
20060 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
20061 xlsb: "application/vnd.ms-excel.sharedStrings"
20062 },
20063 sheets: {
20064 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
20065 xlsb: "application/vnd.ms-excel.worksheet"
20066 },
20067 styles: {/* Styles */
20068 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
20069 xlsb: "application/vnd.ms-excel.styles"
20070 }
20071 };
20072 keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; });
20073 keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
20074 return o;
20075 })();
20076
20077 var type2ct = evert_arr(ct2type);
20078
20079 XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
20080
20081 function parse_ct(data, opts) {
20082 var ctext = {};
20083 if(!data || !data.match) return data;
20084 var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
20085 coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
20086 TODO:[], rels:[], xmlns: "" };
20087 (data.match(tagregex)||[]).forEach(function(x) {
20088 var y = parsexmltag(x);
20089 switch(y[0].replace(nsregex,"<")) {
20090 case '<?xml': break;
20091 case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
20092 case '<Default': ctext[y.Extension] = y.ContentType; break;
20093 case '<Override':
20094 if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
20095 else if(opts.WTF) console.error(y);
20096 break;
20097 }
20098 });
20099 if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
20100 ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
20101 ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
20102 ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
20103 ct.defaults = ctext;
20104 delete ct.calcchains;
20105 return ct;
20106 }
20107
20108 var CTYPE_XML_ROOT = writextag('Types', null, {
20109 'xmlns': XMLNS.CT,
20110 'xmlns:xsd': XMLNS.xsd,
20111 'xmlns:xsi': XMLNS.xsi
20112 });
20113
20114 var CTYPE_DEFAULTS = [
20115 ['xml', 'application/xml'],
20116 ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
20117 ['rels', type2ct.rels[0]]
20118 ].map(function(x) {
20119 return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
20120 });
20121
20122 function write_ct(ct, opts) {
20123 var o = [], v;
20124 o[o.length] = (XML_HEADER);
20125 o[o.length] = (CTYPE_XML_ROOT);
20126 o = o.concat(CTYPE_DEFAULTS);
20127 var f1 = function(w) {
20128 if(ct[w] && ct[w].length > 0) {
20129 v = ct[w][0];
20130 o[o.length] = (writextag('Override', null, {
20131 'PartName': (v[0] == '/' ? "":"/") + v,
20132 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
20133 }));
20134 }
20135 };
20136 var f2 = function(w) {
20137 ct[w].forEach(function(v) {
20138 o[o.length] = (writextag('Override', null, {
20139 'PartName': (v[0] == '/' ? "":"/") + v,
20140 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
20141 }));
20142 });
20143 };
20144 var f3 = function(t) {
20145 (ct[t]||[]).forEach(function(v) {
20146 o[o.length] = (writextag('Override', null, {
20147 'PartName': (v[0] == '/' ? "":"/") + v,
20148 'ContentType': type2ct[t][0]
20149 }));
20150 });
20151 };
20152 f1('workbooks');
20153 f2('sheets');
20154 f3('themes');
20155 ['strs', 'styles'].forEach(f1);
20156 ['coreprops', 'extprops', 'custprops'].forEach(f3);
20157 if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
20158 return o.join("");
20159 }
20160 /* 9.3.2 OPC Relationships Markup */
20161 var RELS = {
20162 WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
20163 SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
20164 };
20165
20166 function parse_rels(data, currentFilePath) {
20167 if (!data) return data;
20168 if (currentFilePath.charAt(0) !== '/') {
20169 currentFilePath = '/'+currentFilePath;
20170 }
20171 var rels = {};
20172 var hash = {};
20173 var resolveRelativePathIntoAbsolute = function (to) {
20174 var toksFrom = currentFilePath.split('/');
20175 toksFrom.pop(); // folder path
20176 var toksTo = to.split('/');
20177 var reversed = [];
20178 while (toksTo.length !== 0) {
20179 var tokTo = toksTo.shift();
20180 if (tokTo === '..') {
20181 toksFrom.pop();
20182 } else if (tokTo !== '.') {
20183 toksFrom.push(tokTo);
20184 }
20185 }
20186 return toksFrom.join('/');
20187 };
20188
20189 data.match(tagregex).forEach(function(x) {
20190 var y = parsexmltag(x);
20191 /* 9.3.2.2 OPC_Relationships */
20192 if (y[0] === '<Relationship') {
20193 var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
20194 var canonictarget = y.TargetMode === 'External' ? y.Target : resolveRelativePathIntoAbsolute(y.Target);
20195 rels[canonictarget] = rel;
20196 hash[y.Id] = rel;
20197 }
20198 });
20199 rels["!id"] = hash;
20200 return rels;
20201 }
20202
20203 XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
20204
20205 var RELS_ROOT = writextag('Relationships', null, {
20206 //'xmlns:ns0': XMLNS.RELS,
20207 'xmlns': XMLNS.RELS
20208 });
20209
20210 /* TODO */
20211 function write_rels(rels) {
20212 var o = [];
20213 o[o.length] = (XML_HEADER);
20214 o[o.length] = (RELS_ROOT);
20215 keys(rels['!id']).forEach(function(rid) { var rel = rels['!id'][rid];
20216 o[o.length] = (writextag('Relationship', null, rel));
20217 });
20218 if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
20219 return o.join("");
20220 }
20221 /* ECMA-376 Part II 11.1 Core Properties Part */
20222 /* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
20223 var CORE_PROPS = [
20224 ["cp:category", "Category"],
20225 ["cp:contentStatus", "ContentStatus"],
20226 ["cp:keywords", "Keywords"],
20227 ["cp:lastModifiedBy", "LastAuthor"],
20228 ["cp:lastPrinted", "LastPrinted"],
20229 ["cp:revision", "RevNumber"],
20230 ["cp:version", "Version"],
20231 ["dc:creator", "Author"],
20232 ["dc:description", "Comments"],
20233 ["dc:identifier", "Identifier"],
20234 ["dc:language", "Language"],
20235 ["dc:subject", "Subject"],
20236 ["dc:title", "Title"],
20237 ["dcterms:created", "CreatedDate", 'date'],
20238 ["dcterms:modified", "ModifiedDate", 'date']
20239 ];
20240
20241 XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
20242 RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
20243
20244 var CORE_PROPS_REGEX = (function() {
20245 var r = new Array(CORE_PROPS.length);
20246 for(var i = 0; i < CORE_PROPS.length; ++i) {
20247 var f = CORE_PROPS[i];
20248 var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1);
20249 r[i] = new RegExp("<" + g + "[^>]*>(.*)<\/" + g + ">");
20250 }
20251 return r;
20252 })();
20253
20254 function parse_core_props(data) {
20255 var p = {};
20256
20257 for(var i = 0; i < CORE_PROPS.length; ++i) {
20258 var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
20259 if(cur != null && cur.length > 0) p[f[1]] = cur[1];
20260 if(f[2] === 'date' && p[f[1]]) p[f[1]] = new Date(p[f[1]]);
20261 }
20262
20263 return p;
20264 }
20265
20266 var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
20267 //'xmlns': XMLNS.CORE_PROPS,
20268 'xmlns:cp': XMLNS.CORE_PROPS,
20269 'xmlns:dc': XMLNS.dc,
20270 'xmlns:dcterms': XMLNS.dcterms,
20271 'xmlns:dcmitype': XMLNS.dcmitype,
20272 'xmlns:xsi': XMLNS.xsi
20273 });
20274
20275 function cp_doit(f, g, h, o, p) {
20276 if(p[f] != null || g == null || g === "") return;
20277 p[f] = g;
20278 o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
20279 }
20280
20281 function write_core_props(cp, opts) {
20282 var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
20283 if(!cp) return o.join("");
20284
20285
20286 if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
20287 if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
20288
20289 for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
20290 if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
20291 return o.join("");
20292 }
20293 /* 15.2.12.3 Extended File Properties Part */
20294 /* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
20295 var EXT_PROPS = [
20296 ["Application", "Application", "string"],
20297 ["AppVersion", "AppVersion", "string"],
20298 ["Company", "Company", "string"],
20299 ["DocSecurity", "DocSecurity", "string"],
20300 ["Manager", "Manager", "string"],
20301 ["HyperlinksChanged", "HyperlinksChanged", "bool"],
20302 ["SharedDoc", "SharedDoc", "bool"],
20303 ["LinksUpToDate", "LinksUpToDate", "bool"],
20304 ["ScaleCrop", "ScaleCrop", "bool"],
20305 ["HeadingPairs", "HeadingPairs", "raw"],
20306 ["TitlesOfParts", "TitlesOfParts", "raw"]
20307 ];
20308
20309 XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
20310 RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
20311
20312 function parse_ext_props(data, p) {
20313 var q = {}; if(!p) p = {};
20314
20315 EXT_PROPS.forEach(function(f) {
20316 switch(f[2]) {
20317 case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
20318 case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break;
20319 case "raw":
20320 var cur = data.match(new RegExp("<" + f[0] + "[^>]*>(.*)<\/" + f[0] + ">"));
20321 if(cur && cur.length > 0) q[f[1]] = cur[1];
20322 break;
20323 }
20324 });
20325
20326 if(q.HeadingPairs && q.TitlesOfParts) {
20327 var v = parseVector(q.HeadingPairs);
20328 var j = 0, widx = 0;
20329 for(var i = 0; i !== v.length; ++i) {
20330 switch(v[i].v) {
20331 case "Worksheets": widx = j; p.Worksheets = +(v[++i].v); break;
20332 case "Named Ranges": ++i; break; // TODO: Handle Named Ranges
20333 }
20334 }
20335 var parts = parseVector(q.TitlesOfParts).map(function(x) { return utf8read(x.v); });
20336 p.SheetNames = parts.slice(widx, widx + p.Worksheets);
20337 }
20338 return p;
20339 }
20340
20341 var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
20342 'xmlns': XMLNS.EXT_PROPS,
20343 'xmlns:vt': XMLNS.vt
20344 });
20345
20346 function write_ext_props(cp, opts) {
20347 var o = [], p = {}, W = writextag;
20348 if(!cp) cp = {};
20349 cp.Application = "SheetJS";
20350 o[o.length] = (XML_HEADER);
20351 o[o.length] = (EXT_PROPS_XML_ROOT);
20352
20353 EXT_PROPS.forEach(function(f) {
20354 if(cp[f[1]] === undefined) return;
20355 var v;
20356 switch(f[2]) {
20357 case 'string': v = cp[f[1]]; break;
20358 case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
20359 }
20360 if(v !== undefined) o[o.length] = (W(f[0], v));
20361 });
20362
20363 /* TODO: HeadingPairs, TitlesOfParts */
20364 o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
20365 o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
20366 if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
20367 return o.join("");
20368 }
20369 /* 15.2.12.2 Custom File Properties Part */
20370 XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
20371 RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
20372
20373 var custregex = /<[^>]+>[^<]*/g;
20374 function parse_cust_props(data, opts) {
20375 var p = {}, name;
20376 var m = data.match(custregex);
20377 if(m) for(var i = 0; i != m.length; ++i) {
20378 var x = m[i], y = parsexmltag(x);
20379 switch(y[0]) {
20380 case '<?xml': break;
20381 case '<Properties':
20382 if(y.xmlns !== XMLNS.CUST_PROPS) throw "unrecognized xmlns " + y.xmlns;
20383 if(y.xmlnsvt && y.xmlnsvt !== XMLNS.vt) throw "unrecognized vt " + y.xmlnsvt;
20384 break;
20385 case '<property': name = y.name; break;
20386 case '</property>': name = null; break;
20387 default: if (x.indexOf('<vt:') === 0) {
20388 var toks = x.split('>');
20389 var type = toks[0].substring(4), text = toks[1];
20390 /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
20391 switch(type) {
20392 case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
20393 p[name] = unescapexml(text);
20394 break;
20395 case 'bool':
20396 p[name] = parsexmlbool(text, '<vt:bool>');
20397 break;
20398 case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
20399 p[name] = parseInt(text, 10);
20400 break;
20401 case 'r4': case 'r8': case 'decimal':
20402 p[name] = parseFloat(text);
20403 break;
20404 case 'filetime': case 'date':
20405 p[name] = new Date(text);
20406 break;
20407 case 'cy': case 'error':
20408 p[name] = unescapexml(text);
20409 break;
20410 default:
20411 if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
20412 }
20413 } else if(x.substr(0,2) === "</") {
20414 } else if(opts.WTF) throw new Error(x);
20415 }
20416 }
20417 return p;
20418 }
20419
20420 var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
20421 'xmlns': XMLNS.CUST_PROPS,
20422 'xmlns:vt': XMLNS.vt
20423 });
20424
20425 function write_cust_props(cp, opts) {
20426 var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
20427 if(!cp) return o.join("");
20428 var pid = 1;
20429 keys(cp).forEach(function custprop(k) { ++pid;
20430 o[o.length] = (writextag('property', write_vt(cp[k]), {
20431 'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
20432 'pid': pid,
20433 'name': k
20434 }));
20435 });
20436 if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
20437 return o.join("");
20438 }
20439 /* 18.4.1 charset to codepage mapping */
20440 var CS2CP = {
20441 0: 1252, /* ANSI */
20442 1: 65001, /* DEFAULT */
20443 2: 65001, /* SYMBOL */
20444 77: 10000, /* MAC */
20445 128: 932, /* SHIFTJIS */
20446 129: 949, /* HANGUL */
20447 130: 1361, /* JOHAB */
20448 134: 936, /* GB2312 */
20449 136: 950, /* CHINESEBIG5 */
20450 161: 1253, /* GREEK */
20451 162: 1254, /* TURKISH */
20452 163: 1258, /* VIETNAMESE */
20453 177: 1255, /* HEBREW */
20454 178: 1256, /* ARABIC */
20455 186: 1257, /* BALTIC */
20456 204: 1251, /* RUSSIAN */
20457 222: 874, /* THAI */
20458 238: 1250, /* EASTEUROPE */
20459 255: 1252, /* OEM */
20460 69: 6969 /* MISC */
20461 };
20462
20463 /* Parse a list of <r> tags */
20464 var parse_rs = (function parse_rs_factory() {
20465 var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<r>/g, rend = /<\/r>/, nlregex = /\r\n/g;
20466 /* 18.4.7 rPr CT_RPrElt */
20467 var parse_rpr = function parse_rpr(rpr, intro, outro) {
20468 var font = {}, cp = 65001;
20469 var m = rpr.match(tagregex), i = 0;
20470 if(m) for(;i!=m.length; ++i) {
20471 var y = parsexmltag(m[i]);
20472 switch(y[0]) {
20473 /* 18.8.12 condense CT_BooleanProperty */
20474 /* ** not required . */
20475 case '<condense': break;
20476 /* 18.8.17 extend CT_BooleanProperty */
20477 /* ** not required . */
20478 case '<extend': break;
20479 /* 18.8.36 shadow CT_BooleanProperty */
20480 /* ** not required . */
20481 case '<shadow':
20482 /* falls through */
20483 case '<shadow/>': break;
20484
20485 /* 18.4.1 charset CT_IntProperty TODO */
20486 case '<charset':
20487 if(y.val == '1') break;
20488 cp = CS2CP[parseInt(y.val, 10)];
20489 break;
20490
20491 /* 18.4.2 outline CT_BooleanProperty TODO */
20492 case '<outline':
20493 /* falls through */
20494 case '<outline/>': break;
20495
20496 /* 18.4.5 rFont CT_FontName */
20497 case '<rFont': font.name = y.val; break;
20498
20499 /* 18.4.11 sz CT_FontSize */
20500 case '<sz': font.sz = y.val; break;
20501
20502 /* 18.4.10 strike CT_BooleanProperty */
20503 case '<strike':
20504 if(!y.val) break;
20505 /* falls through */
20506 case '<strike/>': font.strike = 1; break;
20507 case '</strike>': break;
20508
20509 /* 18.4.13 u CT_UnderlineProperty */
20510 case '<u':
20511 if(!y.val) break;
20512 /* falls through */
20513 case '<u/>': font.u = 1; break;
20514 case '</u>': break;
20515
20516 /* 18.8.2 b */
20517 case '<b':
20518 if(!y.val) break;
20519 /* falls through */
20520 case '<b/>': font.b = 1; break;
20521 case '</b>': break;
20522
20523 /* 18.8.26 i */
20524 case '<i':
20525 if(!y.val) break;
20526 /* falls through */
20527 case '<i/>': font.i = 1; break;
20528 case '</i>': break;
20529
20530 /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
20531 case '<color':
20532 if(y.rgb) font.color = y.rgb.substr(2,6);
20533 break;
20534
20535 /* 18.8.18 family ST_FontFamily */
20536 case '<family': font.family = y.val; break;
20537
20538 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
20539 case '<vertAlign': break;
20540
20541 /* 18.8.35 scheme CT_FontScheme TODO */
20542 case '<scheme': break;
20543
20544 default:
20545 if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
20546 }
20547 }
20548 /* TODO: These should be generated styles, not inline */
20549 var style = [];
20550 if(font.b) style.push("font-weight: bold;");
20551 if(font.i) style.push("font-style: italic;");
20552 intro.push('<span style="' + style.join("") + '">');
20553 outro.push("</span>");
20554 return cp;
20555 };
20556
20557 /* 18.4.4 r CT_RElt */
20558 function parse_r(r) {
20559 var terms = [[],"",[]];
20560 /* 18.4.12 t ST_Xstring */
20561 var t = r.match(tregex), cp = 65001;
20562 if(!isval(t)) return "";
20563 terms[1] = t[1];
20564
20565 var rpr = r.match(rpregex);
20566 if(isval(rpr)) cp = parse_rpr(rpr[1], terms[0], terms[2]);
20567
20568 return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
20569 }
20570 return function parse_rs(rs) {
20571 return rs.replace(rregex,"").split(rend).map(parse_r).join("");
20572 };
20573 })();
20574
20575 /* 18.4.8 si CT_Rst */
20576 var sitregex = /<t[^>]*>([^<]*)<\/t>/g, sirregex = /<r>/;
20577 function parse_si(x, opts) {
20578 var html = opts ? opts.cellHTML : true;
20579 var z = {};
20580 if(!x) return null;
20581 var y;
20582 /* 18.4.12 t ST_Xstring (Plaintext String) */
20583 if(x.charCodeAt(1) === 116) {
20584 z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
20585 z.r = x;
20586 if(html) z.h = z.t;
20587 }
20588 /* 18.4.4 r CT_RElt (Rich Text Run) */
20589 else if((y = x.match(sirregex))) {
20590 z.r = x;
20591 z.t = utf8read(unescapexml(x.match(sitregex).join("").replace(tagregex,"")));
20592 if(html) z.h = parse_rs(x);
20593 }
20594 /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
20595 /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
20596 return z;
20597 }
20598
20599 /* 18.4 Shared String Table */
20600 var sstr0 = /<sst([^>]*)>([\s\S]*)<\/sst>/;
20601 var sstr1 = /<(?:si|sstItem)>/g;
20602 var sstr2 = /<\/(?:si|sstItem)>/;
20603 function parse_sst_xml(data, opts) {
20604 var s = [], ss;
20605 /* 18.4.9 sst CT_Sst */
20606 var sst = data.match(sstr0);
20607 if(isval(sst)) {
20608 ss = sst[2].replace(sstr1,"").split(sstr2);
20609 for(var i = 0; i != ss.length; ++i) {
20610 var o = parse_si(ss[i], opts);
20611 if(o != null) s[s.length] = o;
20612 }
20613 sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
20614 }
20615 return s;
20616 }
20617
20618 RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
20619 var straywsregex = /^\s|\s$|[\t\n\r]/;
20620 function write_sst_xml(sst, opts) {
20621 if(!opts.bookSST) return "";
20622 var o = [XML_HEADER];
20623 o[o.length] = (writextag('sst', null, {
20624 xmlns: XMLNS.main[0],
20625 count: sst.Count,
20626 uniqueCount: sst.Unique
20627 }));
20628 for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
20629 var s = sst[i];
20630 var sitag = "<si>";
20631 if(s.r) sitag += s.r;
20632 else {
20633 sitag += "<t";
20634 if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
20635 sitag += ">" + escapexml(s.t) + "</t>";
20636 }
20637 sitag += "</si>";
20638 o[o.length] = (sitag);
20639 }
20640 if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
20641 return o.join("");
20642 }
20643 /* [MS-XLSB] 2.4.219 BrtBeginSst */
20644 function parse_BrtBeginSst(data, length) {
20645 return [data.read_shift(4), data.read_shift(4)];
20646 }
20647
20648 /* [MS-XLSB] 2.1.7.45 Shared Strings */
20649 function parse_sst_bin(data, opts) {
20650 var s = [];
20651 var pass = false;
20652 recordhopper(data, function hopper_sst(val, R, RT) {
20653 switch(R.n) {
20654 case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break;
20655 case 'BrtSSTItem': s.push(val); break;
20656 case 'BrtEndSst': return true;
20657 /* TODO: produce a test case with a future record */
20658 case 'BrtFRTBegin': pass = true; break;
20659 case 'BrtFRTEnd': pass = false; break;
20660 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
20661 }
20662 });
20663 return s;
20664 }
20665
20666 function write_BrtBeginSst(sst, o) {
20667 if(!o) o = new_buf(8);
20668 o.write_shift(4, sst.Count);
20669 o.write_shift(4, sst.Unique);
20670 return o;
20671 }
20672
20673 var write_BrtSSTItem = write_RichStr;
20674
20675 function write_sst_bin(sst, opts) {
20676 var ba = buf_array();
20677 write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
20678 for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
20679 write_record(ba, "BrtEndSst");
20680 return ba.end();
20681 }
20682 function hex2RGB(h) {
20683 var o = h.substr(h[0]==="#"?1:0,6);
20684 return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
20685 }
20686 function rgb2Hex(rgb) {
20687 for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
20688 return o.toString(16).toUpperCase().substr(1);
20689 }
20690
20691 function rgb2HSL(rgb) {
20692 var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
20693 var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
20694 if(C === 0) return [0, 0, R];
20695
20696 var H6 = 0, S = 0, L2 = (M + m);
20697 S = C / (L2 > 1 ? 2 - L2 : L2);
20698 switch(M){
20699 case R: H6 = ((G - B) / C + 6)%6; break;
20700 case G: H6 = ((B - R) / C + 2); break;
20701 case B: H6 = ((R - G) / C + 4); break;
20702 }
20703 return [H6 / 6, S, L2 / 2];
20704 }
20705
20706 function hsl2RGB(hsl){
20707 var H = hsl[0], S = hsl[1], L = hsl[2];
20708 var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
20709 var rgb = [m,m,m], h6 = 6*H;
20710
20711 var X;
20712 if(S !== 0) switch(h6|0) {
20713 case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
20714 case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
20715 case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
20716 case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
20717 case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
20718 case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
20719 }
20720 for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
20721 return rgb;
20722 }
20723
20724 /* 18.8.3 bgColor tint algorithm */
20725 function rgb_tint(hex, tint) {
20726 if(tint === 0) return hex;
20727 var hsl = rgb2HSL(hex2RGB(hex));
20728 if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
20729 else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
20730 return rgb2Hex(hsl2RGB(hsl));
20731 }
20732
20733 /* 18.3.1.13 width calculations */
20734 var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
20735 function width2px(width) { return (( width + ((128/MDW)|0)/256 )* MDW )|0; }
20736 function px2char(px) { return (((px - 5)/MDW * 100 + 0.5)|0)/100; }
20737 function char2width(chr) { return (((chr * MDW + 5)/MDW*256)|0)/256; }
20738 function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
20739 function find_mdw(collw, coll) {
20740 if(cycle_width(collw) != collw) {
20741 for(MDW=DEF_MDW; MDW>MIN_MDW; --MDW) if(cycle_width(collw) === collw) break;
20742 if(MDW === MIN_MDW) for(MDW=DEF_MDW+1; MDW<MAX_MDW; ++MDW) if(cycle_width(collw) === collw) break;
20743 if(MDW === MAX_MDW) MDW = DEF_MDW;
20744 }
20745 }
20746 var styles = {}; // shared styles
20747
20748 var themes = {}; // shared themes
20749
20750 /* 18.8.21 fills CT_Fills */
20751 function parse_fills(t, opts) {
20752 styles.Fills = [];
20753 var fill = {};
20754 t[0].match(tagregex).forEach(function(x) {
20755 var y = parsexmltag(x);
20756 switch(y[0]) {
20757 case '<fills': case '<fills>': case '</fills>': break;
20758
20759 /* 18.8.20 fill CT_Fill */
20760 case '<fill>': break;
20761 case '</fill>': styles.Fills.push(fill); fill = {}; break;
20762
20763 /* 18.8.32 patternFill CT_PatternFill */
20764 case '<patternFill':
20765 if(y.patternType) fill.patternType = y.patternType;
20766 break;
20767 case '<patternFill/>': case '</patternFill>': break;
20768
20769 /* 18.8.3 bgColor CT_Color */
20770 case '<bgColor':
20771 if(!fill.bgColor) fill.bgColor = {};
20772 if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
20773 if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
20774 if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
20775 /* Excel uses ARGB strings */
20776 if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
20777 break;
20778 case '<bgColor/>': case '</bgColor>': break;
20779
20780 /* 18.8.19 fgColor CT_Color */
20781 case '<fgColor':
20782 if(!fill.fgColor) fill.fgColor = {};
20783 if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
20784 if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
20785 /* Excel uses ARGB strings */
20786 if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
20787 break;
20788 case '<bgColor/>': case '</fgColor>': break;
20789
20790 default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
20791 }
20792 });
20793 }
20794
20795 /* 18.8.31 numFmts CT_NumFmts */
20796 function parse_numFmts(t, opts) {
20797 styles.NumberFmt = [];
20798 var k = keys(SSF._table);
20799 for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
20800 var m = t[0].match(tagregex);
20801 for(i=0; i < m.length; ++i) {
20802 var y = parsexmltag(m[i]);
20803 switch(y[0]) {
20804 case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
20805 case '<numFmt': {
20806 var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
20807 styles.NumberFmt[j] = f; if(j>0) SSF.load(f,j);
20808 } break;
20809 default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
20810 }
20811 }
20812 }
20813
20814 function write_numFmts(NF, opts) {
20815 var o = ["<numFmts>"];
20816 [[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) {
20817 for(var i = r[0]; i <= r[1]; ++i) if(NF[i] !== undefined) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
20818 });
20819 if(o.length === 1) return "";
20820 o[o.length] = ("</numFmts>");
20821 o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
20822 return o.join("");
20823 }
20824
20825 /* 18.8.10 cellXfs CT_CellXfs */
20826 function parse_cellXfs(t, opts) {
20827 styles.CellXf = [];
20828 t[0].match(tagregex).forEach(function(x) {
20829 var y = parsexmltag(x);
20830 switch(y[0]) {
20831 case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
20832
20833 /* 18.8.45 xf CT_Xf */
20834 case '<xf': delete y[0];
20835 if(y.numFmtId) y.numFmtId = parseInt(y.numFmtId, 10);
20836 if(y.fillId) y.fillId = parseInt(y.fillId, 10);
20837 styles.CellXf.push(y); break;
20838 case '</xf>': break;
20839
20840 /* 18.8.1 alignment CT_CellAlignment */
20841 case '<alignment': case '<alignment/>': break;
20842
20843 /* 18.8.33 protection CT_CellProtection */
20844 case '<protection': case '</protection>': case '<protection/>': break;
20845
20846 case '<extLst': case '</extLst>': break;
20847 case '<ext': break;
20848 default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in cellXfs';
20849 }
20850 });
20851 }
20852
20853 function write_cellXfs(cellXfs) {
20854 var o = [];
20855 o[o.length] = (writextag('cellXfs',null));
20856 cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
20857 o[o.length] = ("</cellXfs>");
20858 if(o.length === 2) return "";
20859 o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
20860 return o.join("");
20861 }
20862
20863 /* 18.8 Styles CT_Stylesheet*/
20864 var parse_sty_xml= (function make_pstyx() {
20865 var numFmtRegex = /<numFmts([^>]*)>.*<\/numFmts>/;
20866 var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
20867 var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
20868
20869 return function parse_sty_xml(data, opts) {
20870 /* 18.8.39 styleSheet CT_Stylesheet */
20871 var t;
20872
20873 /* numFmts CT_NumFmts ? */
20874 if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
20875
20876 /* fonts CT_Fonts ? */
20877 // if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);
20878
20879 /* fills CT_Fills */
20880 if((t=data.match(fillsRegex))) parse_fills(t, opts);
20881
20882 /* borders CT_Borders ? */
20883 /* cellStyleXfs CT_CellStyleXfs ? */
20884
20885 /* cellXfs CT_CellXfs ? */
20886 if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
20887
20888 /* dxfs CT_Dxfs ? */
20889 /* tableStyles CT_TableStyles ? */
20890 /* colors CT_Colors ? */
20891 /* extLst CT_ExtensionList ? */
20892
20893 return styles;
20894 };
20895 })();
20896
20897 var STYLES_XML_ROOT = writextag('styleSheet', null, {
20898 'xmlns': XMLNS.main[0],
20899 'xmlns:vt': XMLNS.vt
20900 });
20901
20902 RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
20903
20904 function write_sty_xml(wb, opts) {
20905 var o = [XML_HEADER, STYLES_XML_ROOT], w;
20906 if((w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
20907 o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
20908 o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
20909 o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
20910 o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
20911 if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
20912 o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
20913 o[o.length] = ('<dxfs count="0"/>');
20914 o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
20915
20916 if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
20917 return o.join("");
20918 }
20919 /* [MS-XLSB] 2.4.651 BrtFmt */
20920 function parse_BrtFmt(data, length) {
20921 var ifmt = data.read_shift(2);
20922 var stFmtCode = parse_XLWideString(data,length-2);
20923 return [ifmt, stFmtCode];
20924 }
20925
20926 /* [MS-XLSB] 2.4.653 BrtFont TODO */
20927 function parse_BrtFont(data, length) {
20928 var out = {flags:{}};
20929 out.dyHeight = data.read_shift(2);
20930 out.grbit = parse_FontFlags(data, 2);
20931 out.bls = data.read_shift(2);
20932 out.sss = data.read_shift(2);
20933 out.uls = data.read_shift(1);
20934 out.bFamily = data.read_shift(1);
20935 out.bCharSet = data.read_shift(1);
20936 data.l++;
20937 out.brtColor = parse_BrtColor(data, 8);
20938 out.bFontScheme = data.read_shift(1);
20939 out.name = parse_XLWideString(data, length - 21);
20940
20941 out.flags.Bold = out.bls === 0x02BC;
20942 out.flags.Italic = out.grbit.fItalic;
20943 out.flags.Strikeout = out.grbit.fStrikeout;
20944 out.flags.Outline = out.grbit.fOutline;
20945 out.flags.Shadow = out.grbit.fShadow;
20946 out.flags.Condense = out.grbit.fCondense;
20947 out.flags.Extend = out.grbit.fExtend;
20948 out.flags.Sub = out.sss & 0x2;
20949 out.flags.Sup = out.sss & 0x1;
20950 return out;
20951 }
20952
20953 /* [MS-XLSB] 2.4.816 BrtXF */
20954 function parse_BrtXF(data, length) {
20955 var ixfeParent = data.read_shift(2);
20956 var ifmt = data.read_shift(2);
20957 parsenoop(data, length-4);
20958 return {ixfe:ixfeParent, ifmt:ifmt };
20959 }
20960
20961 /* [MS-XLSB] 2.1.7.50 Styles */
20962 function parse_sty_bin(data, opts) {
20963 styles.NumberFmt = [];
20964 for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
20965
20966 styles.CellXf = [];
20967 var state = ""; /* TODO: this should be a stack */
20968 var pass = false;
20969 recordhopper(data, function hopper_sty(val, R, RT) {
20970 switch(R.n) {
20971 case 'BrtFmt':
20972 styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
20973 break;
20974 case 'BrtFont': break; /* TODO */
20975 case 'BrtKnownFonts': break; /* TODO */
20976 case 'BrtFill': break; /* TODO */
20977 case 'BrtBorder': break; /* TODO */
20978 case 'BrtXF':
20979 if(state === "CELLXFS") {
20980 styles.CellXf.push(val);
20981 }
20982 break; /* TODO */
20983 case 'BrtStyle': break; /* TODO */
20984 case 'BrtDXF': break; /* TODO */
20985 case 'BrtMRUColor': break; /* TODO */
20986 case 'BrtIndexedColor': break; /* TODO */
20987 case 'BrtBeginStyleSheet': break;
20988 case 'BrtEndStyleSheet': break;
20989 case 'BrtBeginTableStyle': break;
20990 case 'BrtTableStyleElement': break;
20991 case 'BrtEndTableStyle': break;
20992 case 'BrtBeginFmts': state = "FMTS"; break;
20993 case 'BrtEndFmts': state = ""; break;
20994 case 'BrtBeginFonts': state = "FONTS"; break;
20995 case 'BrtEndFonts': state = ""; break;
20996 case 'BrtACBegin': state = "ACFONTS"; break;
20997 case 'BrtACEnd': state = ""; break;
20998 case 'BrtBeginFills': state = "FILLS"; break;
20999 case 'BrtEndFills': state = ""; break;
21000 case 'BrtBeginBorders': state = "BORDERS"; break;
21001 case 'BrtEndBorders': state = ""; break;
21002 case 'BrtBeginCellStyleXFs': state = "CELLSTYLEXFS"; break;
21003 case 'BrtEndCellStyleXFs': state = ""; break;
21004 case 'BrtBeginCellXFs': state = "CELLXFS"; break;
21005 case 'BrtEndCellXFs': state = ""; break;
21006 case 'BrtBeginStyles': state = "STYLES"; break;
21007 case 'BrtEndStyles': state = ""; break;
21008 case 'BrtBeginDXFs': state = "DXFS"; break;
21009 case 'BrtEndDXFs': state = ""; break;
21010 case 'BrtBeginTableStyles': state = "TABLESTYLES"; break;
21011 case 'BrtEndTableStyles': state = ""; break;
21012 case 'BrtBeginColorPalette': state = "COLORPALETTE"; break;
21013 case 'BrtEndColorPalette': state = ""; break;
21014 case 'BrtBeginIndexedColors': state = "INDEXEDCOLORS"; break;
21015 case 'BrtEndIndexedColors': state = ""; break;
21016 case 'BrtBeginMRUColors': state = "MRUCOLORS"; break;
21017 case 'BrtEndMRUColors': state = ""; break;
21018 case 'BrtFRTBegin': pass = true; break;
21019 case 'BrtFRTEnd': pass = false; break;
21020 case 'BrtBeginStyleSheetExt14': break;
21021 case 'BrtBeginSlicerStyles': break;
21022 case 'BrtEndSlicerStyles': break;
21023 case 'BrtBeginTimelineStylesheetExt15': break;
21024 case 'BrtEndTimelineStylesheetExt15': break;
21025 case 'BrtBeginTimelineStyles': break;
21026 case 'BrtEndTimelineStyles': break;
21027 case 'BrtEndStyleSheetExt14': break;
21028 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
21029 }
21030 });
21031 return styles;
21032 }
21033
21034 /* [MS-XLSB] 2.1.7.50 Styles */
21035 function write_sty_bin(data, opts) {
21036 var ba = buf_array();
21037 write_record(ba, "BrtBeginStyleSheet");
21038 /* [FMTS] */
21039 /* [FONTS] */
21040 /* [FILLS] */
21041 /* [BORDERS] */
21042 /* CELLSTYLEXFS */
21043 /* CELLXFS*/
21044 /* STYLES */
21045 /* DXFS */
21046 /* TABLESTYLES */
21047 /* [COLORPALETTE] */
21048 /* FRTSTYLESHEET*/
21049 write_record(ba, "BrtEndStyleSheet");
21050 return ba.end();
21051 }
21052 RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
21053
21054 /* 20.1.6.2 clrScheme CT_ColorScheme */
21055 function parse_clrScheme(t, opts) {
21056 themes.themeElements.clrScheme = [];
21057 var color = {};
21058 t[0].match(tagregex).forEach(function(x) {
21059 var y = parsexmltag(x);
21060 switch(y[0]) {
21061 case '<a:clrScheme': case '</a:clrScheme>': break;
21062
21063 /* 20.1.2.3.32 srgbClr CT_SRgbColor */
21064 case '<a:srgbClr': color.rgb = y.val; break;
21065
21066 /* 20.1.2.3.33 sysClr CT_SystemColor */
21067 case '<a:sysClr': color.rgb = y.lastClr; break;
21068
21069 /* 20.1.4.1.9 dk1 (Dark 1) */
21070 case '<a:dk1>':
21071 case '</a:dk1>':
21072 /* 20.1.4.1.10 dk2 (Dark 2) */
21073 case '<a:dk2>':
21074 case '</a:dk2>':
21075 /* 20.1.4.1.22 lt1 (Light 1) */
21076 case '<a:lt1>':
21077 case '</a:lt1>':
21078 /* 20.1.4.1.23 lt2 (Light 2) */
21079 case '<a:lt2>':
21080 case '</a:lt2>':
21081 /* 20.1.4.1.1 accent1 (Accent 1) */
21082 case '<a:accent1>':
21083 case '</a:accent1>':
21084 /* 20.1.4.1.2 accent2 (Accent 2) */
21085 case '<a:accent2>':
21086 case '</a:accent2>':
21087 /* 20.1.4.1.3 accent3 (Accent 3) */
21088 case '<a:accent3>':
21089 case '</a:accent3>':
21090 /* 20.1.4.1.4 accent4 (Accent 4) */
21091 case '<a:accent4>':
21092 case '</a:accent4>':
21093 /* 20.1.4.1.5 accent5 (Accent 5) */
21094 case '<a:accent5>':
21095 case '</a:accent5>':
21096 /* 20.1.4.1.6 accent6 (Accent 6) */
21097 case '<a:accent6>':
21098 case '</a:accent6>':
21099 /* 20.1.4.1.19 hlink (Hyperlink) */
21100 case '<a:hlink>':
21101 case '</a:hlink>':
21102 /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
21103 case '<a:folHlink>':
21104 case '</a:folHlink>':
21105 if (y[0][1] === '/') {
21106 themes.themeElements.clrScheme.push(color);
21107 color = {};
21108 } else {
21109 color.name = y[0].substring(3, y[0].length - 1);
21110 }
21111 break;
21112
21113 default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme';
21114 }
21115 });
21116 }
21117
21118 var clrsregex = /<a:clrScheme([^>]*)>.*<\/a:clrScheme>/;
21119 /* 14.2.7 Theme Part */
21120 function parse_theme_xml(data, opts) {
21121 if(!data || data.length === 0) return themes;
21122 themes.themeElements = {};
21123
21124 var t;
21125
21126 /* clrScheme CT_ColorScheme */
21127 if((t=data.match(clrsregex))) parse_clrScheme(t, opts);
21128
21129 return themes;
21130 }
21131
21132 function write_theme() { return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="1F497D"/></a:dk2><a:lt2><a:srgbClr val="EEECE1"/></a:lt2><a:accent1><a:srgbClr val="4F81BD"/></a:accent1><a:accent2><a:srgbClr val="C0504D"/></a:accent2><a:accent3><a:srgbClr val="9BBB59"/></a:accent3><a:accent4><a:srgbClr val="8064A2"/></a:accent4><a:accent5><a:srgbClr val="4BACC6"/></a:accent5><a:accent6><a:srgbClr val="F79646"/></a:accent6><a:hlink><a:srgbClr val="0000FF"/></a:hlink><a:folHlink><a:srgbClr val="800080"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Cambria"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS Pゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="宋体"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:majorFont><a:minorFont><a:latin typeface="Calibri"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS Pゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="宋体"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000"/><a:shade val="100000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000"/><a:shade val="100000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000"/><a:satMod val="105000"/></a:schemeClr></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst><a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0"/></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000"/></a:lightRig></a:scene3d><a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:spDef><a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style></a:spDef><a:lnDef><a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style></a:lnDef></a:objectDefaults><a:extraClrSchemeLst/></a:theme>'; }
21133 /* 18.6 Calculation Chain */
21134 function parse_cc_xml(data, opts) {
21135 var d = [];
21136 var l = 0, i = 1;
21137 (data.match(tagregex)||[]).forEach(function(x) {
21138 var y = parsexmltag(x);
21139 switch(y[0]) {
21140 case '<?xml': break;
21141 /* 18.6.2 calcChain CT_CalcChain 1 */
21142 case '<calcChain': case '<calcChain>': case '</calcChain>': break;
21143 /* 18.6.1 c CT_CalcCell 1 */
21144 case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
21145 }
21146 });
21147 return d;
21148 }
21149
21150 function write_cc_xml(data, opts) { }
21151 /* [MS-XLSB] 2.6.4.1 */
21152 function parse_BrtCalcChainItem$(data, length) {
21153 var out = {};
21154 out.i = data.read_shift(4);
21155 var cell = {};
21156 cell.r = data.read_shift(4);
21157 cell.c = data.read_shift(4);
21158 out.r = encode_cell(cell);
21159 var flags = data.read_shift(1);
21160 if(flags & 0x2) out.l = '1';
21161 if(flags & 0x8) out.a = '1';
21162 return out;
21163 }
21164
21165 /* 18.6 Calculation Chain */
21166 function parse_cc_bin(data, opts) {
21167 var out = [];
21168 var pass = false;
21169 recordhopper(data, function hopper_cc(val, R, RT) {
21170 switch(R.n) {
21171 case 'BrtCalcChainItem$': out.push(val); break;
21172 case 'BrtBeginCalcChain$': break;
21173 case 'BrtEndCalcChain$': break;
21174 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
21175 }
21176 });
21177 return out;
21178 }
21179
21180 function write_cc_bin(data, opts) { }
21181
21182 function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
21183 for(var i = 0; i != dirComments.length; ++i) {
21184 var canonicalpath=dirComments[i];
21185 var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts);
21186 if(!comments || !comments.length) continue;
21187 // find the sheets targeted by these comments
21188 var sheetNames = keys(sheets);
21189 for(var j = 0; j != sheetNames.length; ++j) {
21190 var sheetName = sheetNames[j];
21191 var rels = sheetRels[sheetName];
21192 if(rels) {
21193 var rel = rels[canonicalpath];
21194 if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments);
21195 }
21196 }
21197 }
21198 }
21199
21200 function insertCommentsIntoSheet(sheetName, sheet, comments) {
21201 comments.forEach(function(comment) {
21202 var cell = sheet[comment.ref];
21203 if (!cell) {
21204 cell = {};
21205 sheet[comment.ref] = cell;
21206 var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
21207 var thisCell = decode_cell(comment.ref);
21208 if(range.s.r > thisCell.r) range.s.r = thisCell.r;
21209 if(range.e.r < thisCell.r) range.e.r = thisCell.r;
21210 if(range.s.c > thisCell.c) range.s.c = thisCell.c;
21211 if(range.e.c < thisCell.c) range.e.c = thisCell.c;
21212 var encoded = encode_range(range);
21213 if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
21214 }
21215
21216 if (!cell.c) cell.c = [];
21217 var o = {a: comment.author, t: comment.t, r: comment.r};
21218 if(comment.h) o.h = comment.h;
21219 cell.c.push(o);
21220 });
21221 }
21222
21223 /* 18.7.3 CT_Comment */
21224 function parse_comments_xml(data, opts) {
21225 if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
21226 var authors = [];
21227 var commentList = [];
21228 data.match(/<(?:\w+:)?authors>([^\u2603]*)<\/(?:\w+:)?authors>/)[1].split(/<\/\w*:?author>/).forEach(function(x) {
21229 if(x === "" || x.trim() === "") return;
21230 authors.push(x.match(/<(?:\w+:)?author[^>]*>(.*)/)[1]);
21231 });
21232 (data.match(/<(?:\w+:)?commentList>([^\u2603]*)<\/(?:\w+:)?commentList>/)||["",""])[1].split(/<\/\w*:?comment>/).forEach(function(x, index) {
21233 if(x === "" || x.trim() === "") return;
21234 var y = parsexmltag(x.match(/<(?:\w+:)?comment[^>]*>/)[0]);
21235 var comment = { author: y.authorId && authors[y.authorId] ? authors[y.authorId] : undefined, ref: y.ref, guid: y.guid };
21236 var cell = decode_cell(y.ref);
21237 if(opts.sheetRows && opts.sheetRows <= cell.r) return;
21238 var textMatch = x.match(/<text>([^\u2603]*)<\/text>/);
21239 if (!textMatch || !textMatch[1]) return; // a comment may contain an empty text tag.
21240 var rt = parse_si(textMatch[1]);
21241 comment.r = rt.r;
21242 comment.t = rt.t;
21243 if(opts.cellHTML) comment.h = rt.h;
21244 commentList.push(comment);
21245 });
21246 return commentList;
21247 }
21248
21249 function write_comments_xml(data, opts) { }
21250 /* [MS-XLSB] 2.4.28 BrtBeginComment */
21251 function parse_BrtBeginComment(data, length) {
21252 var out = {};
21253 out.iauthor = data.read_shift(4);
21254 var rfx = parse_UncheckedRfX(data, 16);
21255 out.rfx = rfx.s;
21256 out.ref = encode_cell(rfx.s);
21257 data.l += 16; /*var guid = parse_GUID(data); */
21258 return out;
21259 }
21260
21261 /* [MS-XLSB] 2.4.324 BrtCommentAuthor */
21262 var parse_BrtCommentAuthor = parse_XLWideString;
21263
21264 /* [MS-XLSB] 2.4.325 BrtCommentText */
21265 var parse_BrtCommentText = parse_RichStr;
21266
21267 /* [MS-XLSB] 2.1.7.8 Comments */
21268 function parse_comments_bin(data, opts) {
21269 var out = [];
21270 var authors = [];
21271 var c = {};
21272 var pass = false;
21273 recordhopper(data, function hopper_cmnt(val, R, RT) {
21274 switch(R.n) {
21275 case 'BrtCommentAuthor': authors.push(val); break;
21276 case 'BrtBeginComment': c = val; break;
21277 case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break;
21278 case 'BrtEndComment':
21279 c.author = authors[c.iauthor];
21280 delete c.iauthor;
21281 if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
21282 delete c.rfx; out.push(c); break;
21283 case 'BrtBeginComments': break;
21284 case 'BrtEndComments': break;
21285 case 'BrtBeginCommentAuthors': break;
21286 case 'BrtEndCommentAuthors': break;
21287 case 'BrtBeginCommentList': break;
21288 case 'BrtEndCommentList': break;
21289 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
21290 }
21291 });
21292 return out;
21293 }
21294
21295 function write_comments_bin(data, opts) { }
21296 /* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
21297 function parse_CellParsedFormula(data, length) {
21298 var cce = data.read_shift(4);
21299 return parsenoop(data, length-4);
21300 }
21301 var strs = {}; // shared strings
21302 var _ssfopts = {}; // spreadsheet formatting options
21303
21304 RELS.WS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
21305
21306 function get_sst_id(sst, str) {
21307 for(var i = 0, len = sst.length; i < len; ++i) if(sst[i].t === str) { sst.Count ++; return i; }
21308 sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
21309 }
21310
21311 function get_cell_style(styles, cell, opts) {
21312 var z = opts.revssf[cell.z != null ? cell.z : "General"];
21313 for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
21314 styles[len] = {
21315 numFmtId:z,
21316 fontId:0,
21317 fillId:0,
21318 borderId:0,
21319 xfId:0,
21320 applyNumberFormat:1
21321 };
21322 return len;
21323 }
21324
21325 function safe_format(p, fmtid, fillid, opts) {
21326 try {
21327 if(fmtid === 0) {
21328 if(p.t === 'n') {
21329 if((p.v|0) === p.v) p.w = SSF._general_int(p.v,_ssfopts);
21330 else p.w = SSF._general_num(p.v,_ssfopts);
21331 }
21332 else if(p.v === undefined) return "";
21333 else p.w = SSF._general(p.v,_ssfopts);
21334 }
21335 else p.w = SSF.format(fmtid,p.v,_ssfopts);
21336 if(opts.cellNF) p.z = SSF._table[fmtid];
21337 } catch(e) { if(opts.WTF) throw e; }
21338 if(fillid) try {
21339 p.s = styles.Fills[fillid];
21340 if (p.s.fgColor && p.s.fgColor.theme) {
21341 p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
21342 if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
21343 }
21344 if (p.s.bgColor && p.s.bgColor.theme) {
21345 p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
21346 if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
21347 }
21348 } catch(e) { if(opts.WTF) throw e; }
21349 }
21350 function parse_ws_xml_dim(ws, s) {
21351 var d = safe_decode_range(s);
21352 if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
21353 }
21354 var mergecregex = /<mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
21355 var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
21356 var hlinkregex = /<hyperlink[^>]*\/>/g;
21357 var dimregex = /"(\w*:\w*)"/;
21358 var colregex = /<col[^>]*\/>/g;
21359 /* 18.3 Worksheets */
21360 function parse_ws_xml(data, opts, rels) {
21361 if(!data) return data;
21362 /* 18.3.1.99 worksheet CT_Worksheet */
21363 var s = {};
21364
21365 /* 18.3.1.35 dimension CT_SheetDimension ? */
21366 var ridx = data.indexOf("<dimension");
21367 if(ridx > 0) {
21368 var ref = data.substr(ridx,50).match(dimregex);
21369 if(ref != null) parse_ws_xml_dim(s, ref[1]);
21370 }
21371
21372 /* 18.3.1.55 mergeCells CT_MergeCells */
21373 var mergecells = [];
21374 if(data.indexOf("</mergeCells>")!==-1) {
21375 var merges = data.match(mergecregex);
21376 for(ridx = 0; ridx != merges.length; ++ridx)
21377 mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));
21378 }
21379
21380 /* 18.3.1.17 cols CT_Cols */
21381 var columns = [];
21382 if(opts.cellStyles && data.indexOf("</cols>")!==-1) {
21383 /* 18.3.1.13 col CT_Col */
21384 var cols = data.match(colregex);
21385 parse_ws_xml_cols(columns, cols);
21386 }
21387
21388 var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
21389
21390 /* 18.3.1.80 sheetData CT_SheetData ? */
21391 var mtch=data.match(sheetdataregex);
21392 if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
21393
21394 /* 18.3.1.48 hyperlinks CT_Hyperlinks */
21395 if(data.indexOf("</hyperlinks>")!==-1) parse_ws_xml_hlinks(s, data.match(hlinkregex), rels);
21396
21397 if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
21398 if(opts.sheetRows > 0 && s["!ref"]) {
21399 var tmpref = safe_decode_range(s["!ref"]);
21400 if(opts.sheetRows < +tmpref.e.r) {
21401 tmpref.e.r = opts.sheetRows - 1;
21402 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
21403 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
21404 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
21405 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
21406 s["!fullref"] = s["!ref"];
21407 s["!ref"] = encode_range(tmpref);
21408 }
21409 }
21410 if(mergecells.length > 0) s["!merges"] = mergecells;
21411 if(columns.length > 0) s["!cols"] = columns;
21412 return s;
21413 }
21414
21415
21416 function parse_ws_xml_hlinks(s, data, rels) {
21417 for(var i = 0; i != data.length; ++i) {
21418 var val = parsexmltag(data[i], true);
21419 if(!val.ref) return;
21420 var rel = rels['!id'][val.id];
21421 if(rel) {
21422 val.Target = rel.Target;
21423 if(val.location) val.Target += "#"+val.location;
21424 val.Rel = rel;
21425 }
21426 var rng = safe_decode_range(val.ref);
21427 for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
21428 var addr = encode_cell({c:C,r:R});
21429 if(!s[addr]) s[addr] = {t:"str",v:undefined};
21430 s[addr].l = val;
21431 }
21432 }
21433 }
21434
21435 function parse_ws_xml_cols(columns, cols) {
21436 var seencol = false;
21437 for(var coli = 0; coli != cols.length; ++coli) {
21438 var coll = parsexmltag(cols[coli], true);
21439 var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
21440 delete coll.min; delete coll.max;
21441 if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
21442 if(coll.width) {
21443 coll.wpx = width2px(+coll.width);
21444 coll.wch = px2char(coll.wpx);
21445 coll.MDW = MDW;
21446 }
21447 while(colm <= colM) columns[colm++] = coll;
21448 }
21449 }
21450
21451 function write_ws_xml_cols(ws, cols) {
21452 var o = ["<cols>"], col, width;
21453 for(var i = 0; i != cols.length; ++i) {
21454 if(!(col = cols[i])) continue;
21455 var p = {min:i+1,max:i+1};
21456 /* wch (chars), wpx (pixels) */
21457 width = -1;
21458 if(col.wpx) width = px2char(col.wpx);
21459 else if(col.wch) width = col.wch;
21460 if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
21461 o[o.length] = (writextag('col', null, p));
21462 }
21463 o[o.length] = "</cols>";
21464 return o.join("");
21465 }
21466
21467 function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
21468 if(cell.v === undefined) return "";
21469 var vv = "";
21470 switch(cell.t) {
21471 case 'b': vv = cell.v ? "1" : "0"; break;
21472 case 'n': case 'e': vv = ''+cell.v; break;
21473 default: vv = cell.v; break;
21474 }
21475 var v = writetag('v', escapexml(vv)), o = {r:ref};
21476 /* TODO: cell style */
21477 var os = get_cell_style(opts.cellXfs, cell, opts);
21478 if(os !== 0) o.s = os;
21479 switch(cell.t) {
21480 case 'n': break;
21481 case 'b': o.t = "b"; break;
21482 case 'e': o.t = "e"; break;
21483 default:
21484 if(opts.bookSST) {
21485 v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
21486 o.t = "s"; break;
21487 }
21488 o.t = "str"; break;
21489 }
21490 return writextag('c', v, o);
21491 }
21492
21493 var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
21494 var cellregex = /<(?:\w+:)?c /, rowregex = /<\/(?:\w+:)?row>/;
21495 var rregex = /r=["']([^"']*)["']/, isregex = /<is>([\S\s]*?)<\/is>/;
21496 var match_v = matchtag("v"), match_f = matchtag("f");
21497
21498 return function parse_ws_xml_data(sdata, s, opts, guess) {
21499 var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p;
21500 var tag;
21501 var sstr;
21502 var fmtid = 0, fillid = 0, do_format = Array.isArray(styles.CellXf), cf;
21503 for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
21504 x = marr[mt].trim();
21505 var xlen = x.length;
21506 if(xlen === 0) continue;
21507
21508 /* 18.3.1.73 row CT_Row */
21509 for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
21510 tag = parsexmltag(x.substr(0,ri), true);
21511 var tagr = parseInt(tag.r, 10);
21512 if(opts.sheetRows && opts.sheetRows < tagr) continue;
21513 if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
21514 if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
21515
21516 /* 18.3.1.4 c CT_Cell */
21517 cells = x.substr(ri).split(cellregex);
21518 for(ri = 1, cellen = cells.length; ri != cellen; ++ri) {
21519 x = cells[ri].trim();
21520 if(x.length === 0) continue;
21521 cref = x.match(rregex); idx = ri; i=0; cc=0;
21522 x = "<c " + x;
21523 if(cref !== null && cref.length === 2) {
21524 idx = 0; d=cref[1];
21525 for(i=0; i != d.length; ++i) {
21526 if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
21527 idx = 26*idx + cc;
21528 }
21529 --idx;
21530 }
21531
21532 for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
21533 tag = parsexmltag(x.substr(0,i), true);
21534 d = x.substr(i);
21535 p = {t:""};
21536
21537 if((cref=d.match(match_v))!== null) p.v=unescapexml(cref[1]);
21538 if(opts.cellFormula && (cref=d.match(match_f))!== null) p.f=unescapexml(cref[1]);
21539
21540 /* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
21541 if(tag.t === undefined && p.v === undefined) {
21542 if(!opts.sheetStubs) continue;
21543 p.t = "str";
21544 }
21545 else p.t = tag.t || "n";
21546 if(guess.s.c > idx) guess.s.c = idx;
21547 if(guess.e.c < idx) guess.e.c = idx;
21548 /* 18.18.11 t ST_CellType */
21549 switch(p.t) {
21550 case 'n': p.v = parseFloat(p.v); break;
21551 case 's':
21552 sstr = strs[parseInt(p.v, 10)];
21553 p.v = sstr.t;
21554 p.r = sstr.r;
21555 if(opts.cellHTML) p.h = sstr.h;
21556 break;
21557 case 'str': if(p.v != null) p.v = utf8read(p.v); else p.v = ""; break;
21558 case 'inlineStr':
21559 cref = d.match(isregex);
21560 p.t = 'str';
21561 if(cref !== null) { sstr = parse_si(cref[1]); p.v = sstr.t; } else p.v = "";
21562 break; // inline string
21563 case 'b': p.v = parsexmlbool(p.v); break;
21564 case 'd':
21565 p.v = datenum(p.v);
21566 p.t = 'n';
21567 break;
21568 /* in case of error, stick value in .raw */
21569 case 'e': p.raw = RBErr[p.v]; break;
21570 }
21571 /* formatting */
21572 fmtid = fillid = 0;
21573 if(do_format && tag.s !== undefined) {
21574 cf = styles.CellXf[tag.s];
21575 if(cf != null) {
21576 if(cf.numFmtId != null) fmtid = cf.numFmtId;
21577 if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
21578 }
21579 }
21580 safe_format(p, fmtid, fillid, opts);
21581 s[tag.r] = p;
21582 }
21583 }
21584 }; })();
21585
21586 function write_ws_xml_data(ws, opts, idx, wb) {
21587 var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R, C;
21588 for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
21589 for(R = range.s.r; R <= range.e.r; ++R) {
21590 r = [];
21591 rr = encode_row(R);
21592 for(C = range.s.c; C <= range.e.c; ++C) {
21593 ref = cols[C] + rr;
21594 if(ws[ref] === undefined) continue;
21595 if((cell = write_ws_xml_cell(ws[ref], ref, ws, opts, idx, wb)) != null) r.push(cell);
21596 }
21597 if(r.length > 0) o[o.length] = (writextag('row', r.join(""), {r:rr}));
21598 }
21599 return o.join("");
21600 }
21601
21602 var WS_XML_ROOT = writextag('worksheet', null, {
21603 'xmlns': XMLNS.main[0],
21604 'xmlns:r': XMLNS.r
21605 });
21606
21607 function write_ws_xml(idx, opts, wb) {
21608 var o = [XML_HEADER, WS_XML_ROOT];
21609 var s = wb.SheetNames[idx], sidx = 0, rdata = "";
21610 var ws = wb.Sheets[s];
21611 if(ws === undefined) ws = {};
21612 var ref = ws['!ref']; if(ref === undefined) ref = 'A1';
21613 o[o.length] = (writextag('dimension', null, {'ref': ref}));
21614
21615 if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
21616 o[sidx = o.length] = '<sheetData/>';
21617 if(ws['!ref'] !== undefined) {
21618 rdata = write_ws_xml_data(ws, opts, idx, wb);
21619 if(rdata.length > 0) o[o.length] = (rdata);
21620 }
21621 if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
21622
21623 if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
21624 return o.join("");
21625 }
21626
21627 /* [MS-XLSB] 2.4.718 BrtRowHdr */
21628 function parse_BrtRowHdr(data, length) {
21629 var z = [];
21630 z.r = data.read_shift(4);
21631 data.l += length-4;
21632 return z;
21633 }
21634
21635 /* [MS-XLSB] 2.4.812 BrtWsDim */
21636 var parse_BrtWsDim = parse_UncheckedRfX;
21637 var write_BrtWsDim = write_UncheckedRfX;
21638
21639 /* [MS-XLSB] 2.4.815 BrtWsProp */
21640 function parse_BrtWsProp(data, length) {
21641 var z = {};
21642 /* TODO: pull flags */
21643 data.l += 19;
21644 z.name = parse_CodeName(data, length - 19);
21645 return z;
21646 }
21647
21648 /* [MS-XLSB] 2.4.303 BrtCellBlank */
21649 function parse_BrtCellBlank(data, length) {
21650 var cell = parse_Cell(data);
21651 return [cell];
21652 }
21653 function write_BrtCellBlank(cell, val, o) {
21654 if(o == null) o = new_buf(8);
21655 return write_Cell(val, o);
21656 }
21657
21658
21659 /* [MS-XLSB] 2.4.304 BrtCellBool */
21660 function parse_BrtCellBool(data, length) {
21661 var cell = parse_Cell(data);
21662 var fBool = data.read_shift(1);
21663 return [cell, fBool, 'b'];
21664 }
21665
21666 /* [MS-XLSB] 2.4.305 BrtCellError */
21667 function parse_BrtCellError(data, length) {
21668 var cell = parse_Cell(data);
21669 var fBool = data.read_shift(1);
21670 return [cell, fBool, 'e'];
21671 }
21672
21673 /* [MS-XLSB] 2.4.308 BrtCellIsst */
21674 function parse_BrtCellIsst(data, length) {
21675 var cell = parse_Cell(data);
21676 var isst = data.read_shift(4);
21677 return [cell, isst, 's'];
21678 }
21679
21680 /* [MS-XLSB] 2.4.310 BrtCellReal */
21681 function parse_BrtCellReal(data, length) {
21682 var cell = parse_Cell(data);
21683 var value = parse_Xnum(data);
21684 return [cell, value, 'n'];
21685 }
21686
21687 /* [MS-XLSB] 2.4.311 BrtCellRk */
21688 function parse_BrtCellRk(data, length) {
21689 var cell = parse_Cell(data);
21690 var value = parse_RkNumber(data);
21691 return [cell, value, 'n'];
21692 }
21693
21694 /* [MS-XLSB] 2.4.314 BrtCellSt */
21695 function parse_BrtCellSt(data, length) {
21696 var cell = parse_Cell(data);
21697 var value = parse_XLWideString(data);
21698 return [cell, value, 'str'];
21699 }
21700
21701 /* [MS-XLSB] 2.4.647 BrtFmlaBool */
21702 function parse_BrtFmlaBool(data, length, opts) {
21703 var cell = parse_Cell(data);
21704 var value = data.read_shift(1);
21705 var o = [cell, value, 'b'];
21706 if(opts.cellFormula) {
21707 var formula = parse_CellParsedFormula(data, length-9);
21708 o[3] = ""; /* TODO */
21709 }
21710 else data.l += length-9;
21711 return o;
21712 }
21713
21714 /* [MS-XLSB] 2.4.648 BrtFmlaError */
21715 function parse_BrtFmlaError(data, length, opts) {
21716 var cell = parse_Cell(data);
21717 var value = data.read_shift(1);
21718 var o = [cell, value, 'e'];
21719 if(opts.cellFormula) {
21720 var formula = parse_CellParsedFormula(data, length-9);
21721 o[3] = ""; /* TODO */
21722 }
21723 else data.l += length-9;
21724 return o;
21725 }
21726
21727 /* [MS-XLSB] 2.4.649 BrtFmlaNum */
21728 function parse_BrtFmlaNum(data, length, opts) {
21729 var cell = parse_Cell(data);
21730 var value = parse_Xnum(data);
21731 var o = [cell, value, 'n'];
21732 if(opts.cellFormula) {
21733 var formula = parse_CellParsedFormula(data, length - 16);
21734 o[3] = ""; /* TODO */
21735 }
21736 else data.l += length-16;
21737 return o;
21738 }
21739
21740 /* [MS-XLSB] 2.4.650 BrtFmlaString */
21741 function parse_BrtFmlaString(data, length, opts) {
21742 var start = data.l;
21743 var cell = parse_Cell(data);
21744 var value = parse_XLWideString(data);
21745 var o = [cell, value, 'str'];
21746 if(opts.cellFormula) {
21747 var formula = parse_CellParsedFormula(data, start + length - data.l);
21748 }
21749 else data.l = start + length;
21750 return o;
21751 }
21752
21753 /* [MS-XLSB] 2.4.676 BrtMergeCell */
21754 var parse_BrtMergeCell = parse_UncheckedRfX;
21755
21756 /* [MS-XLSB] 2.4.656 BrtHLink */
21757 function parse_BrtHLink(data, length, opts) {
21758 var end = data.l + length;
21759 var rfx = parse_UncheckedRfX(data, 16);
21760 var relId = parse_XLNullableWideString(data);
21761 var loc = parse_XLWideString(data);
21762 var tooltip = parse_XLWideString(data);
21763 var display = parse_XLWideString(data);
21764 data.l = end;
21765 return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
21766 }
21767
21768 /* [MS-XLSB] 2.1.7.61 Worksheet */
21769 function parse_ws_bin(data, opts, rels) {
21770 if(!data) return data;
21771 if(!rels) rels = {'!id':{}};
21772 var s = {};
21773
21774 var ref;
21775 var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
21776
21777 var pass = false, end = false;
21778 var row, p, cf, R, C, addr, sstr, rr;
21779 var mergecells = [];
21780 recordhopper(data, function ws_parse(val, R) {
21781 if(end) return;
21782 switch(R.n) {
21783 case 'BrtWsDim': ref = val; break;
21784 case 'BrtRowHdr':
21785 row = val;
21786 if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
21787 rr = encode_row(row.r);
21788 break;
21789
21790 case 'BrtFmlaBool':
21791 case 'BrtFmlaError':
21792 case 'BrtFmlaNum':
21793 case 'BrtFmlaString':
21794 case 'BrtCellBool':
21795 case 'BrtCellError':
21796 case 'BrtCellIsst':
21797 case 'BrtCellReal':
21798 case 'BrtCellRk':
21799 case 'BrtCellSt':
21800 p = {t:val[2]};
21801 switch(val[2]) {
21802 case 'n': p.v = val[1]; break;
21803 case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
21804 case 'b': p.v = val[1] ? true : false; break;
21805 case 'e': p.raw = val[1]; p.v = BErr[p.raw]; break;
21806 case 'str': p.v = utf8read(val[1]); break;
21807 }
21808 if(opts.cellFormula && val.length > 3) p.f = val[3];
21809 if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
21810 s[encode_col(C=val[0].c) + rr] = p;
21811 if(refguess.s.r > row.r) refguess.s.r = row.r;
21812 if(refguess.s.c > C) refguess.s.c = C;
21813 if(refguess.e.r < row.r) refguess.e.r = row.r;
21814 if(refguess.e.c < C) refguess.e.c = C;
21815 break;
21816
21817 case 'BrtCellBlank': if(!opts.sheetStubs) break;
21818 p = {t:'str',v:undefined};
21819 s[encode_col(C=val[0].c) + rr] = p;
21820 if(refguess.s.r > row.r) refguess.s.r = row.r;
21821 if(refguess.s.c > C) refguess.s.c = C;
21822 if(refguess.e.r < row.r) refguess.e.r = row.r;
21823 if(refguess.e.c < C) refguess.e.c = C;
21824 break;
21825
21826 /* Merge Cells */
21827 case 'BrtBeginMergeCells': break;
21828 case 'BrtEndMergeCells': break;
21829 case 'BrtMergeCell': mergecells.push(val); break;
21830
21831 case 'BrtHLink':
21832 var rel = rels['!id'][val.relId];
21833 if(rel) {
21834 val.Target = rel.Target;
21835 if(val.loc) val.Target += "#"+val.loc;
21836 val.Rel = rel;
21837 }
21838 for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
21839 addr = encode_cell({c:C,r:R});
21840 if(!s[addr]) s[addr] = {t:"str",v:undefined};
21841 s[addr].l = val;
21842 }
21843 break;
21844
21845 case 'BrtArrFmla': break; // TODO
21846 case 'BrtShrFmla': break; // TODO
21847 case 'BrtBeginSheet': break;
21848 case 'BrtWsProp': break; // TODO
21849 case 'BrtSheetCalcProp': break; // TODO
21850 case 'BrtBeginWsViews': break; // TODO
21851 case 'BrtBeginWsView': break; // TODO
21852 case 'BrtPane': break; // TODO
21853 case 'BrtSel': break; // TODO
21854 case 'BrtEndWsView': break; // TODO
21855 case 'BrtEndWsViews': break; // TODO
21856 case 'BrtACBegin': break; // TODO
21857 case 'BrtRwDescent': break; // TODO
21858 case 'BrtACEnd': break; // TODO
21859 case 'BrtWsFmtInfoEx14': break; // TODO
21860 case 'BrtWsFmtInfo': break; // TODO
21861 case 'BrtBeginColInfos': break; // TODO
21862 case 'BrtColInfo': break; // TODO
21863 case 'BrtEndColInfos': break; // TODO
21864 case 'BrtBeginSheetData': break; // TODO
21865 case 'BrtEndSheetData': break; // TODO
21866 case 'BrtSheetProtection': break; // TODO
21867 case 'BrtPrintOptions': break; // TODO
21868 case 'BrtMargins': break; // TODO
21869 case 'BrtPageSetup': break; // TODO
21870 case 'BrtFRTBegin': pass = true; break;
21871 case 'BrtFRTEnd': pass = false; break;
21872 case 'BrtEndSheet': break; // TODO
21873 case 'BrtDrawing': break; // TODO
21874 case 'BrtLegacyDrawing': break; // TODO
21875 case 'BrtLegacyDrawingHF': break; // TODO
21876 case 'BrtPhoneticInfo': break; // TODO
21877 case 'BrtBeginHeaderFooter': break; // TODO
21878 case 'BrtEndHeaderFooter': break; // TODO
21879 case 'BrtBrk': break; // TODO
21880 case 'BrtBeginRwBrk': break; // TODO
21881 case 'BrtEndRwBrk': break; // TODO
21882 case 'BrtBeginColBrk': break; // TODO
21883 case 'BrtEndColBrk': break; // TODO
21884 case 'BrtBeginUserShViews': break; // TODO
21885 case 'BrtBeginUserShView': break; // TODO
21886 case 'BrtEndUserShView': break; // TODO
21887 case 'BrtEndUserShViews': break; // TODO
21888 case 'BrtBkHim': break; // TODO
21889 case 'BrtBeginOleObjects': break; // TODO
21890 case 'BrtOleObject': break; // TODO
21891 case 'BrtEndOleObjects': break; // TODO
21892 case 'BrtBeginListParts': break; // TODO
21893 case 'BrtListPart': break; // TODO
21894 case 'BrtEndListParts': break; // TODO
21895 case 'BrtBeginSortState': break; // TODO
21896 case 'BrtBeginSortCond': break; // TODO
21897 case 'BrtEndSortCond': break; // TODO
21898 case 'BrtEndSortState': break; // TODO
21899 case 'BrtBeginConditionalFormatting': break; // TODO
21900 case 'BrtEndConditionalFormatting': break; // TODO
21901 case 'BrtBeginCFRule': break; // TODO
21902 case 'BrtEndCFRule': break; // TODO
21903 case 'BrtBeginDVals': break; // TODO
21904 case 'BrtDVal': break; // TODO
21905 case 'BrtEndDVals': break; // TODO
21906 case 'BrtRangeProtection': break; // TODO
21907 case 'BrtBeginDCon': break; // TODO
21908 case 'BrtEndDCon': break; // TODO
21909 case 'BrtBeginDRefs': break;
21910 case 'BrtDRef': break;
21911 case 'BrtEndDRefs': break;
21912
21913 /* ActiveX */
21914 case 'BrtBeginActiveXControls': break;
21915 case 'BrtActiveX': break;
21916 case 'BrtEndActiveXControls': break;
21917
21918 /* AutoFilter */
21919 case 'BrtBeginAFilter': break;
21920 case 'BrtEndAFilter': break;
21921 case 'BrtBeginFilterColumn': break;
21922 case 'BrtBeginFilters': break;
21923 case 'BrtFilter': break;
21924 case 'BrtEndFilters': break;
21925 case 'BrtEndFilterColumn': break;
21926 case 'BrtDynamicFilter': break;
21927 case 'BrtTop10Filter': break;
21928 case 'BrtBeginCustomFilters': break;
21929 case 'BrtCustomFilter': break;
21930 case 'BrtEndCustomFilters': break;
21931
21932 /* Smart Tags */
21933 case 'BrtBeginSmartTags': break;
21934 case 'BrtBeginCellSmartTags': break;
21935 case 'BrtBeginCellSmartTag': break;
21936 case 'BrtCellSmartTagProperty': break;
21937 case 'BrtEndCellSmartTag': break;
21938 case 'BrtEndCellSmartTags': break;
21939 case 'BrtEndSmartTags': break;
21940
21941 /* Cell Watch */
21942 case 'BrtBeginCellWatches': break;
21943 case 'BrtCellWatch': break;
21944 case 'BrtEndCellWatches': break;
21945
21946 /* Table */
21947 case 'BrtTable': break;
21948
21949 /* Ignore Cell Errors */
21950 case 'BrtBeginCellIgnoreECs': break;
21951 case 'BrtCellIgnoreEC': break;
21952 case 'BrtEndCellIgnoreECs': break;
21953
21954 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n);
21955 }
21956 }, opts);
21957 if(!s["!ref"] && (refguess.s.r < 1000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref);
21958 if(opts.sheetRows && s["!ref"]) {
21959 var tmpref = safe_decode_range(s["!ref"]);
21960 if(opts.sheetRows < +tmpref.e.r) {
21961 tmpref.e.r = opts.sheetRows - 1;
21962 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
21963 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
21964 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
21965 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
21966 s["!fullref"] = s["!ref"];
21967 s["!ref"] = encode_range(tmpref);
21968 }
21969 }
21970 if(mergecells.length > 0) s["!merges"] = mergecells;
21971 return s;
21972 }
21973
21974 /* TODO: something useful -- this is a stub */
21975 function write_ws_bin_cell(ba, cell, R, C, opts) {
21976 if(cell.v === undefined) return "";
21977 var vv = "";
21978 switch(cell.t) {
21979 case 'b': vv = cell.v ? "1" : "0"; break;
21980 case 'n': case 'e': vv = ''+cell.v; break;
21981 default: vv = cell.v; break;
21982 }
21983 var o = {r:R, c:C};
21984 /* TODO: cell style */
21985 o.s = get_cell_style(opts.cellXfs, cell, opts);
21986 switch(cell.t) {
21987 case 's': case 'str':
21988 if(opts.bookSST) {
21989 vv = get_sst_id(opts.Strings, cell.v);
21990 o.t = "s"; break;
21991 }
21992 o.t = "str"; break;
21993 case 'n': break;
21994 case 'b': o.t = "b"; break;
21995 case 'e': o.t = "e"; break;
21996 }
21997 write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
21998 }
21999
22000 function write_CELLTABLE(ba, ws, idx, opts, wb) {
22001 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
22002 write_record(ba, 'BrtBeginSheetData');
22003 for(var R = range.s.r; R <= range.e.r; ++R) {
22004 rr = encode_row(R);
22005 /* [ACCELLTABLE] */
22006 /* BrtRowHdr */
22007 for(var C = range.s.c; C <= range.e.c; ++C) {
22008 /* *16384CELL */
22009 if(R === range.s.r) cols[C] = encode_col(C);
22010 ref = cols[C] + rr;
22011 if(!ws[ref]) continue;
22012 /* write cell */
22013 write_ws_bin_cell(ba, ws[ref], R, C, opts);
22014 }
22015 }
22016 write_record(ba, 'BrtEndSheetData');
22017 }
22018
22019 function write_ws_bin(idx, opts, wb) {
22020 var ba = buf_array();
22021 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
22022 var r = safe_decode_range(ws['!ref'] || "A1");
22023 write_record(ba, "BrtBeginSheet");
22024 /* [BrtWsProp] */
22025 write_record(ba, "BrtWsDim", write_BrtWsDim(r));
22026 /* [WSVIEWS2] */
22027 /* [WSFMTINFO] */
22028 /* *COLINFOS */
22029 write_CELLTABLE(ba, ws, idx, opts, wb);
22030 /* [BrtSheetCalcProp] */
22031 /* [[BrtSheetProtectionIso] BrtSheetProtection] */
22032 /* *([BrtRangeProtectionIso] BrtRangeProtection) */
22033 /* [SCENMAN] */
22034 /* [AUTOFILTER] */
22035 /* [SORTSTATE] */
22036 /* [DCON] */
22037 /* [USERSHVIEWS] */
22038 /* [MERGECELLS] */
22039 /* [BrtPhoneticInfo] */
22040 /* *CONDITIONALFORMATTING */
22041 /* [DVALS] */
22042 /* *BrtHLink */
22043 /* [BrtPrintOptions] */
22044 /* [BrtMargins] */
22045 /* [BrtPageSetup] */
22046 /* [HEADERFOOTER] */
22047 /* [RWBRK] */
22048 /* [COLBRK] */
22049 /* *BrtBigName */
22050 /* [CELLWATCHES] */
22051 /* [IGNOREECS] */
22052 /* [SMARTTAGS] */
22053 /* [BrtDrawing] */
22054 /* [BrtLegacyDrawing] */
22055 /* [BrtLegacyDrawingHF] */
22056 /* [BrtBkHim] */
22057 /* [OLEOBJECTS] */
22058 /* [ACTIVEXCONTROLS] */
22059 /* [WEBPUBITEMS] */
22060 /* [LISTPARTS] */
22061 /* FRTWORKSHEET */
22062 write_record(ba, "BrtEndSheet");
22063 return ba.end();
22064 }
22065 /* 18.2.28 (CT_WorkbookProtection) Defaults */
22066 var WBPropsDef = [
22067 ['allowRefreshQuery', '0'],
22068 ['autoCompressPictures', '1'],
22069 ['backupFile', '0'],
22070 ['checkCompatibility', '0'],
22071 ['codeName', ''],
22072 ['date1904', '0'],
22073 ['dateCompatibility', '1'],
22074 //['defaultThemeVersion', '0'],
22075 ['filterPrivacy', '0'],
22076 ['hidePivotFieldList', '0'],
22077 ['promptedSolutions', '0'],
22078 ['publishItems', '0'],
22079 ['refreshAllConnections', false],
22080 ['saveExternalLinkValues', '1'],
22081 ['showBorderUnselectedTables', '1'],
22082 ['showInkAnnotation', '1'],
22083 ['showObjects', 'all'],
22084 ['showPivotChartFilter', '0']
22085 //['updateLinks', 'userSet']
22086 ];
22087
22088 /* 18.2.30 (CT_BookView) Defaults */
22089 var WBViewDef = [
22090 ['activeTab', '0'],
22091 ['autoFilterDateGrouping', '1'],
22092 ['firstSheet', '0'],
22093 ['minimized', '0'],
22094 ['showHorizontalScroll', '1'],
22095 ['showSheetTabs', '1'],
22096 ['showVerticalScroll', '1'],
22097 ['tabRatio', '600'],
22098 ['visibility', 'visible']
22099 //window{Height,Width}, {x,y}Window
22100 ];
22101
22102 /* 18.2.19 (CT_Sheet) Defaults */
22103 var SheetDef = [
22104 ['state', 'visible']
22105 ];
22106
22107 /* 18.2.2 (CT_CalcPr) Defaults */
22108 var CalcPrDef = [
22109 ['calcCompleted', 'true'],
22110 ['calcMode', 'auto'],
22111 ['calcOnSave', 'true'],
22112 ['concurrentCalc', 'true'],
22113 ['fullCalcOnLoad', 'false'],
22114 ['fullPrecision', 'true'],
22115 ['iterate', 'false'],
22116 ['iterateCount', '100'],
22117 ['iterateDelta', '0.001'],
22118 ['refMode', 'A1']
22119 ];
22120
22121 /* 18.2.3 (CT_CustomWorkbookView) Defaults */
22122 var CustomWBViewDef = [
22123 ['autoUpdate', 'false'],
22124 ['changesSavedWin', 'false'],
22125 ['includeHiddenRowCol', 'true'],
22126 ['includePrintSettings', 'true'],
22127 ['maximized', 'false'],
22128 ['minimized', 'false'],
22129 ['onlySync', 'false'],
22130 ['personalView', 'false'],
22131 ['showComments', 'commIndicator'],
22132 ['showFormulaBar', 'true'],
22133 ['showHorizontalScroll', 'true'],
22134 ['showObjects', 'all'],
22135 ['showSheetTabs', 'true'],
22136 ['showStatusbar', 'true'],
22137 ['showVerticalScroll', 'true'],
22138 ['tabRatio', '600'],
22139 ['xWindow', '0'],
22140 ['yWindow', '0']
22141 ];
22142
22143 function push_defaults_array(target, defaults) {
22144 for(var j = 0; j != target.length; ++j) { var w = target[j];
22145 for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
22146 if(w[z[0]] == null) w[z[0]] = z[1];
22147 }
22148 }
22149 }
22150 function push_defaults(target, defaults) {
22151 for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
22152 if(target[z[0]] == null) target[z[0]] = z[1];
22153 }
22154 }
22155
22156 function parse_wb_defaults(wb) {
22157 push_defaults(wb.WBProps, WBPropsDef);
22158 push_defaults(wb.CalcPr, CalcPrDef);
22159
22160 push_defaults_array(wb.WBView, WBViewDef);
22161 push_defaults_array(wb.Sheets, SheetDef);
22162
22163 _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
22164 }
22165 /* 18.2 Workbook */
22166 var wbnsregex = /<\w+:workbook/;
22167 function parse_wb_xml(data, opts) {
22168 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
22169 var pass = false, xmlns = "xmlns";
22170 data.match(tagregex).forEach(function xml_wb(x) {
22171 var y = parsexmltag(x);
22172 switch(strip_ns(y[0])) {
22173 case '<?xml': break;
22174
22175 /* 18.2.27 workbook CT_Workbook 1 */
22176 case '<workbook':
22177 if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
22178 wb.xmlns = y[xmlns];
22179 break;
22180 case '</workbook>': break;
22181
22182 /* 18.2.13 fileVersion CT_FileVersion ? */
22183 case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
22184 case '<fileVersion/>': break;
22185
22186 /* 18.2.12 fileSharing CT_FileSharing ? */
22187 case '<fileSharing': case '<fileSharing/>': break;
22188
22189 /* 18.2.28 workbookPr CT_WorkbookPr ? */
22190 case '<workbookPr': delete y[0]; wb.WBProps = y; break;
22191 case '<workbookPr/>': delete y[0]; wb.WBProps = y; break;
22192
22193 /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
22194 case '<workbookProtection': break;
22195 case '<workbookProtection/>': break;
22196
22197 /* 18.2.1 bookViews CT_BookViews ? */
22198 case '<bookViews>': case '</bookViews>': break;
22199 /* 18.2.30 workbookView CT_BookView + */
22200 case '<workbookView': delete y[0]; wb.WBView.push(y); break;
22201
22202 /* 18.2.20 sheets CT_Sheets 1 */
22203 case '<sheets>': case '</sheets>': break; // aggregate sheet
22204 /* 18.2.19 sheet CT_Sheet + */
22205 case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
22206
22207 /* 18.2.15 functionGroups CT_FunctionGroups ? */
22208 case '<functionGroups': case '<functionGroups/>': break;
22209 /* 18.2.14 functionGroup CT_FunctionGroup + */
22210 case '<functionGroup': break;
22211
22212 /* 18.2.9 externalReferences CT_ExternalReferences ? */
22213 case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
22214 /* 18.2.8 externalReference CT_ExternalReference + */
22215 case '<externalReference': break;
22216
22217 /* 18.2.6 definedNames CT_DefinedNames ? */
22218 case '<definedNames/>': break;
22219 case '<definedNames>': case '<definedNames': pass=true; break;
22220 case '</definedNames>': pass=false; break;
22221 /* 18.2.5 definedName CT_DefinedName + */
22222 case '<definedName': case '<definedName/>': case '</definedName>': break;
22223
22224 /* 18.2.2 calcPr CT_CalcPr ? */
22225 case '<calcPr': delete y[0]; wb.CalcPr = y; break;
22226 case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
22227
22228 /* 18.2.16 oleSize CT_OleSize ? (ref required) */
22229 case '<oleSize': break;
22230
22231 /* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
22232 case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
22233 /* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
22234 case '<customWorkbookView': case '</customWorkbookView>': break;
22235
22236 /* 18.2.18 pivotCaches CT_PivotCaches ? */
22237 case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
22238 /* 18.2.17 pivotCache CT_PivotCache ? */
22239 case '<pivotCache': break;
22240
22241 /* 18.2.21 smartTagPr CT_SmartTagPr ? */
22242 case '<smartTagPr': case '<smartTagPr/>': break;
22243
22244 /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
22245 case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
22246 /* 18.2.22 smartTagType CT_SmartTagType ? */
22247 case '<smartTagType': break;
22248
22249 /* 18.2.24 webPublishing CT_WebPublishing ? */
22250 case '<webPublishing': case '<webPublishing/>': break;
22251
22252 /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
22253 case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
22254
22255 /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
22256 case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
22257 /* 18.2.25 webPublishObject CT_WebPublishObject ? */
22258 case '<webPublishObject': break;
22259
22260 /* 18.2.10 extLst CT_ExtensionList ? */
22261 case '<extLst>': case '</extLst>': case '<extLst/>': break;
22262 /* 18.2.7 ext CT_Extension + */
22263 case '<ext': pass=true; break; //TODO: check with versions of excel
22264 case '</ext>': pass=false; break;
22265
22266 /* Others */
22267 case '<ArchID': break;
22268 case '<AlternateContent': pass=true; break;
22269 case '</AlternateContent>': pass=false; break;
22270
22271 default: if(!pass && opts.WTF) throw 'unrecognized ' + y[0] + ' in workbook';
22272 }
22273 });
22274 if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
22275
22276 parse_wb_defaults(wb);
22277
22278 return wb;
22279 }
22280
22281 var WB_XML_ROOT = writextag('workbook', null, {
22282 'xmlns': XMLNS.main[0],
22283 //'xmlns:mx': XMLNS.mx,
22284 //'xmlns:s': XMLNS.main[0],
22285 'xmlns:r': XMLNS.r
22286 });
22287
22288 function safe1904(wb) {
22289 /* TODO: store date1904 somewhere else */
22290 try { return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false"; } catch(e) { return "false"; }
22291 }
22292
22293 function write_wb_xml(wb, opts) {
22294 var o = [XML_HEADER];
22295 o[o.length] = WB_XML_ROOT;
22296 o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
22297 o[o.length] = "<sheets>";
22298 for(var i = 0; i != wb.SheetNames.length; ++i)
22299 o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
22300 o[o.length] = "</sheets>";
22301 if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
22302 return o.join("");
22303 }
22304 /* [MS-XLSB] 2.4.301 BrtBundleSh */
22305 function parse_BrtBundleSh(data, length) {
22306 var z = {};
22307 z.hsState = data.read_shift(4); //ST_SheetState
22308 z.iTabID = data.read_shift(4);
22309 z.strRelID = parse_RelID(data,length-8);
22310 z.name = parse_XLWideString(data);
22311 return z;
22312 }
22313 function write_BrtBundleSh(data, o) {
22314 if(!o) o = new_buf(127);
22315 o.write_shift(4, data.hsState);
22316 o.write_shift(4, data.iTabID);
22317 write_RelID(data.strRelID, o);
22318 write_XLWideString(data.name.substr(0,31), o);
22319 return o;
22320 }
22321
22322 /* [MS-XLSB] 2.4.807 BrtWbProp */
22323 function parse_BrtWbProp(data, length) {
22324 data.read_shift(4);
22325 var dwThemeVersion = data.read_shift(4);
22326 var strName = (length > 8) ? parse_XLWideString(data) : "";
22327 return [dwThemeVersion, strName];
22328 }
22329 function write_BrtWbProp(data, o) {
22330 if(!o) o = new_buf(8);
22331 o.write_shift(4, 0);
22332 o.write_shift(4, 0);
22333 return o;
22334 }
22335
22336 function parse_BrtFRTArchID$(data, length) {
22337 var o = {};
22338 data.read_shift(4);
22339 o.ArchID = data.read_shift(4);
22340 data.l += length - 8;
22341 return o;
22342 }
22343
22344 /* [MS-XLSB] 2.1.7.60 Workbook */
22345 function parse_wb_bin(data, opts) {
22346 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
22347 var pass = false, z;
22348
22349 recordhopper(data, function hopper_wb(val, R) {
22350 switch(R.n) {
22351 case 'BrtBundleSh': wb.Sheets.push(val); break;
22352
22353 case 'BrtBeginBook': break;
22354 case 'BrtFileVersion': break;
22355 case 'BrtWbProp': break;
22356 case 'BrtACBegin': break;
22357 case 'BrtAbsPath15': break;
22358 case 'BrtACEnd': break;
22359 case 'BrtWbFactoid': break;
22360 /*case 'BrtBookProtectionIso': break;*/
22361 case 'BrtBookProtection': break;
22362 case 'BrtBeginBookViews': break;
22363 case 'BrtBookView': break;
22364 case 'BrtEndBookViews': break;
22365 case 'BrtBeginBundleShs': break;
22366 case 'BrtEndBundleShs': break;
22367 case 'BrtBeginFnGroup': break;
22368 case 'BrtEndFnGroup': break;
22369 case 'BrtBeginExternals': break;
22370 case 'BrtSupSelf': break;
22371 case 'BrtSupBookSrc': break;
22372 case 'BrtExternSheet': break;
22373 case 'BrtEndExternals': break;
22374 case 'BrtName': break;
22375 case 'BrtCalcProp': break;
22376 case 'BrtUserBookView': break;
22377 case 'BrtBeginPivotCacheIDs': break;
22378 case 'BrtBeginPivotCacheID': break;
22379 case 'BrtEndPivotCacheID': break;
22380 case 'BrtEndPivotCacheIDs': break;
22381 case 'BrtWebOpt': break;
22382 case 'BrtFileRecover': break;
22383 case 'BrtFileSharing': break;
22384 /*case 'BrtBeginWebPubItems': break;
22385 case 'BrtBeginWebPubItem': break;
22386 case 'BrtEndWebPubItem': break;
22387 case 'BrtEndWebPubItems': break;*/
22388
22389 /* Smart Tags */
22390 case 'BrtBeginSmartTagTypes': break;
22391 case 'BrtSmartTagType': break;
22392 case 'BrtEndSmartTagTypes': break;
22393
22394 case 'BrtFRTBegin': pass = true; break;
22395 case 'BrtFRTArchID$': break;
22396 case 'BrtWorkBookPr15': break;
22397 case 'BrtFRTEnd': pass = false; break;
22398 case 'BrtEndBook': break;
22399 default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n);
22400 }
22401 });
22402
22403 parse_wb_defaults(wb);
22404
22405 return wb;
22406 }
22407
22408 /* [MS-XLSB] 2.1.7.60 Workbook */
22409 function write_BUNDLESHS(ba, wb, opts) {
22410 write_record(ba, "BrtBeginBundleShs");
22411 for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
22412 var d = { hsState: 0, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
22413 write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
22414 }
22415 write_record(ba, "BrtEndBundleShs");
22416 }
22417
22418 /* [MS-XLSB] 2.4.643 BrtFileVersion */
22419 function write_BrtFileVersion(data, o) {
22420 if(!o) o = new_buf(127);
22421 for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
22422 write_XLWideString("SheetJS", o);
22423 write_XLWideString(XLSX.version, o);
22424 write_XLWideString(XLSX.version, o);
22425 write_XLWideString("7262", o);
22426 o.length = o.l;
22427 return o;
22428 }
22429
22430 /* [MS-XLSB] 2.1.7.60 Workbook */
22431 function write_BOOKVIEWS(ba, wb, opts) {
22432 write_record(ba, "BrtBeginBookViews");
22433 /* 1*(BrtBookView *FRT) */
22434 write_record(ba, "BrtEndBookViews");
22435 }
22436
22437 /* [MS-XLSB] 2.4.302 BrtCalcProp */
22438 function write_BrtCalcProp(data, o) {
22439 if(!o) o = new_buf(26);
22440 o.write_shift(4,0); /* force recalc */
22441 o.write_shift(4,1);
22442 o.write_shift(4,0);
22443 write_Xnum(0, o);
22444 o.write_shift(-4, 1023);
22445 o.write_shift(1, 0x33);
22446 o.write_shift(1, 0x00);
22447 return o;
22448 }
22449
22450 function write_BrtFileRecover(data, o) {
22451 if(!o) o = new_buf(1);
22452 o.write_shift(1,0);
22453 return o;
22454 }
22455
22456 /* [MS-XLSB] 2.1.7.60 Workbook */
22457 function write_wb_bin(wb, opts) {
22458 var ba = buf_array();
22459 write_record(ba, "BrtBeginBook");
22460 write_record(ba, "BrtFileVersion", write_BrtFileVersion());
22461 /* [[BrtFileSharingIso] BrtFileSharing] */
22462 write_record(ba, "BrtWbProp", write_BrtWbProp());
22463 /* [ACABSPATH] */
22464 /* [[BrtBookProtectionIso] BrtBookProtection] */
22465 write_BOOKVIEWS(ba, wb, opts);
22466 write_BUNDLESHS(ba, wb, opts);
22467 /* [FNGROUP] */
22468 /* [EXTERNALS] */
22469 /* *BrtName */
22470 write_record(ba, "BrtCalcProp", write_BrtCalcProp());
22471 /* [BrtOleSize] */
22472 /* *(BrtUserBookView *FRT) */
22473 /* [PIVOTCACHEIDS] */
22474 /* [BrtWbFactoid] */
22475 /* [SMARTTAGTYPES] */
22476 /* [BrtWebOpt] */
22477 write_record(ba, "BrtFileRecover", write_BrtFileRecover());
22478 /* [WEBPUBITEMS] */
22479 /* [CRERRS] */
22480 /* FRTWORKBOOK */
22481 write_record(ba, "BrtEndBook");
22482
22483 return ba.end();
22484 }
22485 function parse_wb(data, name, opts) {
22486 return (name.substr(-4)===".bin" ? parse_wb_bin : parse_wb_xml)(data, opts);
22487 }
22488
22489 function parse_ws(data, name, opts, rels) {
22490 return (name.substr(-4)===".bin" ? parse_ws_bin : parse_ws_xml)(data, opts, rels);
22491 }
22492
22493 function parse_sty(data, name, opts) {
22494 return (name.substr(-4)===".bin" ? parse_sty_bin : parse_sty_xml)(data, opts);
22495 }
22496
22497 function parse_theme(data, name, opts) {
22498 return parse_theme_xml(data, opts);
22499 }
22500
22501 function parse_sst(data, name, opts) {
22502 return (name.substr(-4)===".bin" ? parse_sst_bin : parse_sst_xml)(data, opts);
22503 }
22504
22505 function parse_cmnt(data, name, opts) {
22506 return (name.substr(-4)===".bin" ? parse_comments_bin : parse_comments_xml)(data, opts);
22507 }
22508
22509 function parse_cc(data, name, opts) {
22510 return (name.substr(-4)===".bin" ? parse_cc_bin : parse_cc_xml)(data, opts);
22511 }
22512
22513 function write_wb(wb, name, opts) {
22514 return (name.substr(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
22515 }
22516
22517 function write_ws(data, name, opts, wb) {
22518 return (name.substr(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb);
22519 }
22520
22521 function write_sty(data, name, opts) {
22522 return (name.substr(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
22523 }
22524
22525 function write_sst(data, name, opts) {
22526 return (name.substr(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
22527 }
22528 /*
22529 function write_cmnt(data, name, opts) {
22530 return (name.substr(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
22531 }
22532
22533 function write_cc(data, name, opts) {
22534 return (name.substr(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
22535 }
22536 */
22537 /* [MS-XLSB] 2.3 Record Enumeration */
22538 var RecordEnum = {
22539 0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr },
22540 0x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank },
22541 0x0002: { n:"BrtCellRk", f:parse_BrtCellRk },
22542 0x0003: { n:"BrtCellError", f:parse_BrtCellError },
22543 0x0004: { n:"BrtCellBool", f:parse_BrtCellBool },
22544 0x0005: { n:"BrtCellReal", f:parse_BrtCellReal },
22545 0x0006: { n:"BrtCellSt", f:parse_BrtCellSt },
22546 0x0007: { n:"BrtCellIsst", f:parse_BrtCellIsst },
22547 0x0008: { n:"BrtFmlaString", f:parse_BrtFmlaString },
22548 0x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
22549 0x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
22550 0x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
22551 0x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
22552 0x0013: { n:"BrtSSTItem", f:parse_RichStr },
22553 0x0014: { n:"BrtPCDIMissing", f:parsenoop },
22554 0x0015: { n:"BrtPCDINumber", f:parsenoop },
22555 0x0016: { n:"BrtPCDIBoolean", f:parsenoop },
22556 0x0017: { n:"BrtPCDIError", f:parsenoop },
22557 0x0018: { n:"BrtPCDIString", f:parsenoop },
22558 0x0019: { n:"BrtPCDIDatetime", f:parsenoop },
22559 0x001A: { n:"BrtPCDIIndex", f:parsenoop },
22560 0x001B: { n:"BrtPCDIAMissing", f:parsenoop },
22561 0x001C: { n:"BrtPCDIANumber", f:parsenoop },
22562 0x001D: { n:"BrtPCDIABoolean", f:parsenoop },
22563 0x001E: { n:"BrtPCDIAError", f:parsenoop },
22564 0x001F: { n:"BrtPCDIAString", f:parsenoop },
22565 0x0020: { n:"BrtPCDIADatetime", f:parsenoop },
22566 0x0021: { n:"BrtPCRRecord", f:parsenoop },
22567 0x0022: { n:"BrtPCRRecordDt", f:parsenoop },
22568 0x0023: { n:"BrtFRTBegin", f:parsenoop },
22569 0x0024: { n:"BrtFRTEnd", f:parsenoop },
22570 0x0025: { n:"BrtACBegin", f:parsenoop },
22571 0x0026: { n:"BrtACEnd", f:parsenoop },
22572 0x0027: { n:"BrtName", f:parsenoop },
22573 0x0028: { n:"BrtIndexRowBlock", f:parsenoop },
22574 0x002A: { n:"BrtIndexBlock", f:parsenoop },
22575 0x002B: { n:"BrtFont", f:parse_BrtFont },
22576 0x002C: { n:"BrtFmt", f:parse_BrtFmt },
22577 0x002D: { n:"BrtFill", f:parsenoop },
22578 0x002E: { n:"BrtBorder", f:parsenoop },
22579 0x002F: { n:"BrtXF", f:parse_BrtXF },
22580 0x0030: { n:"BrtStyle", f:parsenoop },
22581 0x0031: { n:"BrtCellMeta", f:parsenoop },
22582 0x0032: { n:"BrtValueMeta", f:parsenoop },
22583 0x0033: { n:"BrtMdb", f:parsenoop },
22584 0x0034: { n:"BrtBeginFmd", f:parsenoop },
22585 0x0035: { n:"BrtEndFmd", f:parsenoop },
22586 0x0036: { n:"BrtBeginMdx", f:parsenoop },
22587 0x0037: { n:"BrtEndMdx", f:parsenoop },
22588 0x0038: { n:"BrtBeginMdxTuple", f:parsenoop },
22589 0x0039: { n:"BrtEndMdxTuple", f:parsenoop },
22590 0x003A: { n:"BrtMdxMbrIstr", f:parsenoop },
22591 0x003B: { n:"BrtStr", f:parsenoop },
22592 0x003C: { n:"BrtColInfo", f:parsenoop },
22593 0x003E: { n:"BrtCellRString", f:parsenoop },
22594 0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ },
22595 0x0040: { n:"BrtDVal", f:parsenoop },
22596 0x0041: { n:"BrtSxvcellNum", f:parsenoop },
22597 0x0042: { n:"BrtSxvcellStr", f:parsenoop },
22598 0x0043: { n:"BrtSxvcellBool", f:parsenoop },
22599 0x0044: { n:"BrtSxvcellErr", f:parsenoop },
22600 0x0045: { n:"BrtSxvcellDate", f:parsenoop },
22601 0x0046: { n:"BrtSxvcellNil", f:parsenoop },
22602 0x0080: { n:"BrtFileVersion", f:parsenoop },
22603 0x0081: { n:"BrtBeginSheet", f:parsenoop },
22604 0x0082: { n:"BrtEndSheet", f:parsenoop },
22605 0x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
22606 0x0084: { n:"BrtEndBook", f:parsenoop },
22607 0x0085: { n:"BrtBeginWsViews", f:parsenoop },
22608 0x0086: { n:"BrtEndWsViews", f:parsenoop },
22609 0x0087: { n:"BrtBeginBookViews", f:parsenoop },
22610 0x0088: { n:"BrtEndBookViews", f:parsenoop },
22611 0x0089: { n:"BrtBeginWsView", f:parsenoop },
22612 0x008A: { n:"BrtEndWsView", f:parsenoop },
22613 0x008B: { n:"BrtBeginCsViews", f:parsenoop },
22614 0x008C: { n:"BrtEndCsViews", f:parsenoop },
22615 0x008D: { n:"BrtBeginCsView", f:parsenoop },
22616 0x008E: { n:"BrtEndCsView", f:parsenoop },
22617 0x008F: { n:"BrtBeginBundleShs", f:parsenoop },
22618 0x0090: { n:"BrtEndBundleShs", f:parsenoop },
22619 0x0091: { n:"BrtBeginSheetData", f:parsenoop },
22620 0x0092: { n:"BrtEndSheetData", f:parsenoop },
22621 0x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
22622 0x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
22623 0x0097: { n:"BrtPane", f:parsenoop },
22624 0x0098: { n:"BrtSel", f:parsenoop },
22625 0x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
22626 0x009A: { n:"BrtWbFactoid", f:parsenoop },
22627 0x009B: { n:"BrtFileRecover", f:parsenoop },
22628 0x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
22629 0x009D: { n:"BrtCalcProp", f:parsenoop },
22630 0x009E: { n:"BrtBookView", f:parsenoop },
22631 0x009F: { n:"BrtBeginSst", f:parse_BrtBeginSst },
22632 0x00A0: { n:"BrtEndSst", f:parsenoop },
22633 0x00A1: { n:"BrtBeginAFilter", f:parsenoop },
22634 0x00A2: { n:"BrtEndAFilter", f:parsenoop },
22635 0x00A3: { n:"BrtBeginFilterColumn", f:parsenoop },
22636 0x00A4: { n:"BrtEndFilterColumn", f:parsenoop },
22637 0x00A5: { n:"BrtBeginFilters", f:parsenoop },
22638 0x00A6: { n:"BrtEndFilters", f:parsenoop },
22639 0x00A7: { n:"BrtFilter", f:parsenoop },
22640 0x00A8: { n:"BrtColorFilter", f:parsenoop },
22641 0x00A9: { n:"BrtIconFilter", f:parsenoop },
22642 0x00AA: { n:"BrtTop10Filter", f:parsenoop },
22643 0x00AB: { n:"BrtDynamicFilter", f:parsenoop },
22644 0x00AC: { n:"BrtBeginCustomFilters", f:parsenoop },
22645 0x00AD: { n:"BrtEndCustomFilters", f:parsenoop },
22646 0x00AE: { n:"BrtCustomFilter", f:parsenoop },
22647 0x00AF: { n:"BrtAFilterDateGroupItem", f:parsenoop },
22648 0x00B0: { n:"BrtMergeCell", f:parse_BrtMergeCell },
22649 0x00B1: { n:"BrtBeginMergeCells", f:parsenoop },
22650 0x00B2: { n:"BrtEndMergeCells", f:parsenoop },
22651 0x00B3: { n:"BrtBeginPivotCacheDef", f:parsenoop },
22652 0x00B4: { n:"BrtEndPivotCacheDef", f:parsenoop },
22653 0x00B5: { n:"BrtBeginPCDFields", f:parsenoop },
22654 0x00B6: { n:"BrtEndPCDFields", f:parsenoop },
22655 0x00B7: { n:"BrtBeginPCDField", f:parsenoop },
22656 0x00B8: { n:"BrtEndPCDField", f:parsenoop },
22657 0x00B9: { n:"BrtBeginPCDSource", f:parsenoop },
22658 0x00BA: { n:"BrtEndPCDSource", f:parsenoop },
22659 0x00BB: { n:"BrtBeginPCDSRange", f:parsenoop },
22660 0x00BC: { n:"BrtEndPCDSRange", f:parsenoop },
22661 0x00BD: { n:"BrtBeginPCDFAtbl", f:parsenoop },
22662 0x00BE: { n:"BrtEndPCDFAtbl", f:parsenoop },
22663 0x00BF: { n:"BrtBeginPCDIRun", f:parsenoop },
22664 0x00C0: { n:"BrtEndPCDIRun", f:parsenoop },
22665 0x00C1: { n:"BrtBeginPivotCacheRecords", f:parsenoop },
22666 0x00C2: { n:"BrtEndPivotCacheRecords", f:parsenoop },
22667 0x00C3: { n:"BrtBeginPCDHierarchies", f:parsenoop },
22668 0x00C4: { n:"BrtEndPCDHierarchies", f:parsenoop },
22669 0x00C5: { n:"BrtBeginPCDHierarchy", f:parsenoop },
22670 0x00C6: { n:"BrtEndPCDHierarchy", f:parsenoop },
22671 0x00C7: { n:"BrtBeginPCDHFieldsUsage", f:parsenoop },
22672 0x00C8: { n:"BrtEndPCDHFieldsUsage", f:parsenoop },
22673 0x00C9: { n:"BrtBeginExtConnection", f:parsenoop },
22674 0x00CA: { n:"BrtEndExtConnection", f:parsenoop },
22675 0x00CB: { n:"BrtBeginECDbProps", f:parsenoop },
22676 0x00CC: { n:"BrtEndECDbProps", f:parsenoop },
22677 0x00CD: { n:"BrtBeginECOlapProps", f:parsenoop },
22678 0x00CE: { n:"BrtEndECOlapProps", f:parsenoop },
22679 0x00CF: { n:"BrtBeginPCDSConsol", f:parsenoop },
22680 0x00D0: { n:"BrtEndPCDSConsol", f:parsenoop },
22681 0x00D1: { n:"BrtBeginPCDSCPages", f:parsenoop },
22682 0x00D2: { n:"BrtEndPCDSCPages", f:parsenoop },
22683 0x00D3: { n:"BrtBeginPCDSCPage", f:parsenoop },
22684 0x00D4: { n:"BrtEndPCDSCPage", f:parsenoop },
22685 0x00D5: { n:"BrtBeginPCDSCPItem", f:parsenoop },
22686 0x00D6: { n:"BrtEndPCDSCPItem", f:parsenoop },
22687 0x00D7: { n:"BrtBeginPCDSCSets", f:parsenoop },
22688 0x00D8: { n:"BrtEndPCDSCSets", f:parsenoop },
22689 0x00D9: { n:"BrtBeginPCDSCSet", f:parsenoop },
22690 0x00DA: { n:"BrtEndPCDSCSet", f:parsenoop },
22691 0x00DB: { n:"BrtBeginPCDFGroup", f:parsenoop },
22692 0x00DC: { n:"BrtEndPCDFGroup", f:parsenoop },
22693 0x00DD: { n:"BrtBeginPCDFGItems", f:parsenoop },
22694 0x00DE: { n:"BrtEndPCDFGItems", f:parsenoop },
22695 0x00DF: { n:"BrtBeginPCDFGRange", f:parsenoop },
22696 0x00E0: { n:"BrtEndPCDFGRange", f:parsenoop },
22697 0x00E1: { n:"BrtBeginPCDFGDiscrete", f:parsenoop },
22698 0x00E2: { n:"BrtEndPCDFGDiscrete", f:parsenoop },
22699 0x00E3: { n:"BrtBeginPCDSDTupleCache", f:parsenoop },
22700 0x00E4: { n:"BrtEndPCDSDTupleCache", f:parsenoop },
22701 0x00E5: { n:"BrtBeginPCDSDTCEntries", f:parsenoop },
22702 0x00E6: { n:"BrtEndPCDSDTCEntries", f:parsenoop },
22703 0x00E7: { n:"BrtBeginPCDSDTCEMembers", f:parsenoop },
22704 0x00E8: { n:"BrtEndPCDSDTCEMembers", f:parsenoop },
22705 0x00E9: { n:"BrtBeginPCDSDTCEMember", f:parsenoop },
22706 0x00EA: { n:"BrtEndPCDSDTCEMember", f:parsenoop },
22707 0x00EB: { n:"BrtBeginPCDSDTCQueries", f:parsenoop },
22708 0x00EC: { n:"BrtEndPCDSDTCQueries", f:parsenoop },
22709 0x00ED: { n:"BrtBeginPCDSDTCQuery", f:parsenoop },
22710 0x00EE: { n:"BrtEndPCDSDTCQuery", f:parsenoop },
22711 0x00EF: { n:"BrtBeginPCDSDTCSets", f:parsenoop },
22712 0x00F0: { n:"BrtEndPCDSDTCSets", f:parsenoop },
22713 0x00F1: { n:"BrtBeginPCDSDTCSet", f:parsenoop },
22714 0x00F2: { n:"BrtEndPCDSDTCSet", f:parsenoop },
22715 0x00F3: { n:"BrtBeginPCDCalcItems", f:parsenoop },
22716 0x00F4: { n:"BrtEndPCDCalcItems", f:parsenoop },
22717 0x00F5: { n:"BrtBeginPCDCalcItem", f:parsenoop },
22718 0x00F6: { n:"BrtEndPCDCalcItem", f:parsenoop },
22719 0x00F7: { n:"BrtBeginPRule", f:parsenoop },
22720 0x00F8: { n:"BrtEndPRule", f:parsenoop },
22721 0x00F9: { n:"BrtBeginPRFilters", f:parsenoop },
22722 0x00FA: { n:"BrtEndPRFilters", f:parsenoop },
22723 0x00FB: { n:"BrtBeginPRFilter", f:parsenoop },
22724 0x00FC: { n:"BrtEndPRFilter", f:parsenoop },
22725 0x00FD: { n:"BrtBeginPNames", f:parsenoop },
22726 0x00FE: { n:"BrtEndPNames", f:parsenoop },
22727 0x00FF: { n:"BrtBeginPName", f:parsenoop },
22728 0x0100: { n:"BrtEndPName", f:parsenoop },
22729 0x0101: { n:"BrtBeginPNPairs", f:parsenoop },
22730 0x0102: { n:"BrtEndPNPairs", f:parsenoop },
22731 0x0103: { n:"BrtBeginPNPair", f:parsenoop },
22732 0x0104: { n:"BrtEndPNPair", f:parsenoop },
22733 0x0105: { n:"BrtBeginECWebProps", f:parsenoop },
22734 0x0106: { n:"BrtEndECWebProps", f:parsenoop },
22735 0x0107: { n:"BrtBeginEcWpTables", f:parsenoop },
22736 0x0108: { n:"BrtEndECWPTables", f:parsenoop },
22737 0x0109: { n:"BrtBeginECParams", f:parsenoop },
22738 0x010A: { n:"BrtEndECParams", f:parsenoop },
22739 0x010B: { n:"BrtBeginECParam", f:parsenoop },
22740 0x010C: { n:"BrtEndECParam", f:parsenoop },
22741 0x010D: { n:"BrtBeginPCDKPIs", f:parsenoop },
22742 0x010E: { n:"BrtEndPCDKPIs", f:parsenoop },
22743 0x010F: { n:"BrtBeginPCDKPI", f:parsenoop },
22744 0x0110: { n:"BrtEndPCDKPI", f:parsenoop },
22745 0x0111: { n:"BrtBeginDims", f:parsenoop },
22746 0x0112: { n:"BrtEndDims", f:parsenoop },
22747 0x0113: { n:"BrtBeginDim", f:parsenoop },
22748 0x0114: { n:"BrtEndDim", f:parsenoop },
22749 0x0115: { n:"BrtIndexPartEnd", f:parsenoop },
22750 0x0116: { n:"BrtBeginStyleSheet", f:parsenoop },
22751 0x0117: { n:"BrtEndStyleSheet", f:parsenoop },
22752 0x0118: { n:"BrtBeginSXView", f:parsenoop },
22753 0x0119: { n:"BrtEndSXVI", f:parsenoop },
22754 0x011A: { n:"BrtBeginSXVI", f:parsenoop },
22755 0x011B: { n:"BrtBeginSXVIs", f:parsenoop },
22756 0x011C: { n:"BrtEndSXVIs", f:parsenoop },
22757 0x011D: { n:"BrtBeginSXVD", f:parsenoop },
22758 0x011E: { n:"BrtEndSXVD", f:parsenoop },
22759 0x011F: { n:"BrtBeginSXVDs", f:parsenoop },
22760 0x0120: { n:"BrtEndSXVDs", f:parsenoop },
22761 0x0121: { n:"BrtBeginSXPI", f:parsenoop },
22762 0x0122: { n:"BrtEndSXPI", f:parsenoop },
22763 0x0123: { n:"BrtBeginSXPIs", f:parsenoop },
22764 0x0124: { n:"BrtEndSXPIs", f:parsenoop },
22765 0x0125: { n:"BrtBeginSXDI", f:parsenoop },
22766 0x0126: { n:"BrtEndSXDI", f:parsenoop },
22767 0x0127: { n:"BrtBeginSXDIs", f:parsenoop },
22768 0x0128: { n:"BrtEndSXDIs", f:parsenoop },
22769 0x0129: { n:"BrtBeginSXLI", f:parsenoop },
22770 0x012A: { n:"BrtEndSXLI", f:parsenoop },
22771 0x012B: { n:"BrtBeginSXLIRws", f:parsenoop },
22772 0x012C: { n:"BrtEndSXLIRws", f:parsenoop },
22773 0x012D: { n:"BrtBeginSXLICols", f:parsenoop },
22774 0x012E: { n:"BrtEndSXLICols", f:parsenoop },
22775 0x012F: { n:"BrtBeginSXFormat", f:parsenoop },
22776 0x0130: { n:"BrtEndSXFormat", f:parsenoop },
22777 0x0131: { n:"BrtBeginSXFormats", f:parsenoop },
22778 0x0132: { n:"BrtEndSxFormats", f:parsenoop },
22779 0x0133: { n:"BrtBeginSxSelect", f:parsenoop },
22780 0x0134: { n:"BrtEndSxSelect", f:parsenoop },
22781 0x0135: { n:"BrtBeginISXVDRws", f:parsenoop },
22782 0x0136: { n:"BrtEndISXVDRws", f:parsenoop },
22783 0x0137: { n:"BrtBeginISXVDCols", f:parsenoop },
22784 0x0138: { n:"BrtEndISXVDCols", f:parsenoop },
22785 0x0139: { n:"BrtEndSXLocation", f:parsenoop },
22786 0x013A: { n:"BrtBeginSXLocation", f:parsenoop },
22787 0x013B: { n:"BrtEndSXView", f:parsenoop },
22788 0x013C: { n:"BrtBeginSXTHs", f:parsenoop },
22789 0x013D: { n:"BrtEndSXTHs", f:parsenoop },
22790 0x013E: { n:"BrtBeginSXTH", f:parsenoop },
22791 0x013F: { n:"BrtEndSXTH", f:parsenoop },
22792 0x0140: { n:"BrtBeginISXTHRws", f:parsenoop },
22793 0x0141: { n:"BrtEndISXTHRws", f:parsenoop },
22794 0x0142: { n:"BrtBeginISXTHCols", f:parsenoop },
22795 0x0143: { n:"BrtEndISXTHCols", f:parsenoop },
22796 0x0144: { n:"BrtBeginSXTDMPS", f:parsenoop },
22797 0x0145: { n:"BrtEndSXTDMPs", f:parsenoop },
22798 0x0146: { n:"BrtBeginSXTDMP", f:parsenoop },
22799 0x0147: { n:"BrtEndSXTDMP", f:parsenoop },
22800 0x0148: { n:"BrtBeginSXTHItems", f:parsenoop },
22801 0x0149: { n:"BrtEndSXTHItems", f:parsenoop },
22802 0x014A: { n:"BrtBeginSXTHItem", f:parsenoop },
22803 0x014B: { n:"BrtEndSXTHItem", f:parsenoop },
22804 0x014C: { n:"BrtBeginMetadata", f:parsenoop },
22805 0x014D: { n:"BrtEndMetadata", f:parsenoop },
22806 0x014E: { n:"BrtBeginEsmdtinfo", f:parsenoop },
22807 0x014F: { n:"BrtMdtinfo", f:parsenoop },
22808 0x0150: { n:"BrtEndEsmdtinfo", f:parsenoop },
22809 0x0151: { n:"BrtBeginEsmdb", f:parsenoop },
22810 0x0152: { n:"BrtEndEsmdb", f:parsenoop },
22811 0x0153: { n:"BrtBeginEsfmd", f:parsenoop },
22812 0x0154: { n:"BrtEndEsfmd", f:parsenoop },
22813 0x0155: { n:"BrtBeginSingleCells", f:parsenoop },
22814 0x0156: { n:"BrtEndSingleCells", f:parsenoop },
22815 0x0157: { n:"BrtBeginList", f:parsenoop },
22816 0x0158: { n:"BrtEndList", f:parsenoop },
22817 0x0159: { n:"BrtBeginListCols", f:parsenoop },
22818 0x015A: { n:"BrtEndListCols", f:parsenoop },
22819 0x015B: { n:"BrtBeginListCol", f:parsenoop },
22820 0x015C: { n:"BrtEndListCol", f:parsenoop },
22821 0x015D: { n:"BrtBeginListXmlCPr", f:parsenoop },
22822 0x015E: { n:"BrtEndListXmlCPr", f:parsenoop },
22823 0x015F: { n:"BrtListCCFmla", f:parsenoop },
22824 0x0160: { n:"BrtListTrFmla", f:parsenoop },
22825 0x0161: { n:"BrtBeginExternals", f:parsenoop },
22826 0x0162: { n:"BrtEndExternals", f:parsenoop },
22827 0x0163: { n:"BrtSupBookSrc", f:parsenoop },
22828 0x0165: { n:"BrtSupSelf", f:parsenoop },
22829 0x0166: { n:"BrtSupSame", f:parsenoop },
22830 0x0167: { n:"BrtSupTabs", f:parsenoop },
22831 0x0168: { n:"BrtBeginSupBook", f:parsenoop },
22832 0x0169: { n:"BrtPlaceholderName", f:parsenoop },
22833 0x016A: { n:"BrtExternSheet", f:parsenoop },
22834 0x016B: { n:"BrtExternTableStart", f:parsenoop },
22835 0x016C: { n:"BrtExternTableEnd", f:parsenoop },
22836 0x016E: { n:"BrtExternRowHdr", f:parsenoop },
22837 0x016F: { n:"BrtExternCellBlank", f:parsenoop },
22838 0x0170: { n:"BrtExternCellReal", f:parsenoop },
22839 0x0171: { n:"BrtExternCellBool", f:parsenoop },
22840 0x0172: { n:"BrtExternCellError", f:parsenoop },
22841 0x0173: { n:"BrtExternCellString", f:parsenoop },
22842 0x0174: { n:"BrtBeginEsmdx", f:parsenoop },
22843 0x0175: { n:"BrtEndEsmdx", f:parsenoop },
22844 0x0176: { n:"BrtBeginMdxSet", f:parsenoop },
22845 0x0177: { n:"BrtEndMdxSet", f:parsenoop },
22846 0x0178: { n:"BrtBeginMdxMbrProp", f:parsenoop },
22847 0x0179: { n:"BrtEndMdxMbrProp", f:parsenoop },
22848 0x017A: { n:"BrtBeginMdxKPI", f:parsenoop },
22849 0x017B: { n:"BrtEndMdxKPI", f:parsenoop },
22850 0x017C: { n:"BrtBeginEsstr", f:parsenoop },
22851 0x017D: { n:"BrtEndEsstr", f:parsenoop },
22852 0x017E: { n:"BrtBeginPRFItem", f:parsenoop },
22853 0x017F: { n:"BrtEndPRFItem", f:parsenoop },
22854 0x0180: { n:"BrtBeginPivotCacheIDs", f:parsenoop },
22855 0x0181: { n:"BrtEndPivotCacheIDs", f:parsenoop },
22856 0x0182: { n:"BrtBeginPivotCacheID", f:parsenoop },
22857 0x0183: { n:"BrtEndPivotCacheID", f:parsenoop },
22858 0x0184: { n:"BrtBeginISXVIs", f:parsenoop },
22859 0x0185: { n:"BrtEndISXVIs", f:parsenoop },
22860 0x0186: { n:"BrtBeginColInfos", f:parsenoop },
22861 0x0187: { n:"BrtEndColInfos", f:parsenoop },
22862 0x0188: { n:"BrtBeginRwBrk", f:parsenoop },
22863 0x0189: { n:"BrtEndRwBrk", f:parsenoop },
22864 0x018A: { n:"BrtBeginColBrk", f:parsenoop },
22865 0x018B: { n:"BrtEndColBrk", f:parsenoop },
22866 0x018C: { n:"BrtBrk", f:parsenoop },
22867 0x018D: { n:"BrtUserBookView", f:parsenoop },
22868 0x018E: { n:"BrtInfo", f:parsenoop },
22869 0x018F: { n:"BrtCUsr", f:parsenoop },
22870 0x0190: { n:"BrtUsr", f:parsenoop },
22871 0x0191: { n:"BrtBeginUsers", f:parsenoop },
22872 0x0193: { n:"BrtEOF", f:parsenoop },
22873 0x0194: { n:"BrtUCR", f:parsenoop },
22874 0x0195: { n:"BrtRRInsDel", f:parsenoop },
22875 0x0196: { n:"BrtRREndInsDel", f:parsenoop },
22876 0x0197: { n:"BrtRRMove", f:parsenoop },
22877 0x0198: { n:"BrtRREndMove", f:parsenoop },
22878 0x0199: { n:"BrtRRChgCell", f:parsenoop },
22879 0x019A: { n:"BrtRREndChgCell", f:parsenoop },
22880 0x019B: { n:"BrtRRHeader", f:parsenoop },
22881 0x019C: { n:"BrtRRUserView", f:parsenoop },
22882 0x019D: { n:"BrtRRRenSheet", f:parsenoop },
22883 0x019E: { n:"BrtRRInsertSh", f:parsenoop },
22884 0x019F: { n:"BrtRRDefName", f:parsenoop },
22885 0x01A0: { n:"BrtRRNote", f:parsenoop },
22886 0x01A1: { n:"BrtRRConflict", f:parsenoop },
22887 0x01A2: { n:"BrtRRTQSIF", f:parsenoop },
22888 0x01A3: { n:"BrtRRFormat", f:parsenoop },
22889 0x01A4: { n:"BrtRREndFormat", f:parsenoop },
22890 0x01A5: { n:"BrtRRAutoFmt", f:parsenoop },
22891 0x01A6: { n:"BrtBeginUserShViews", f:parsenoop },
22892 0x01A7: { n:"BrtBeginUserShView", f:parsenoop },
22893 0x01A8: { n:"BrtEndUserShView", f:parsenoop },
22894 0x01A9: { n:"BrtEndUserShViews", f:parsenoop },
22895 0x01AA: { n:"BrtArrFmla", f:parsenoop },
22896 0x01AB: { n:"BrtShrFmla", f:parsenoop },
22897 0x01AC: { n:"BrtTable", f:parsenoop },
22898 0x01AD: { n:"BrtBeginExtConnections", f:parsenoop },
22899 0x01AE: { n:"BrtEndExtConnections", f:parsenoop },
22900 0x01AF: { n:"BrtBeginPCDCalcMems", f:parsenoop },
22901 0x01B0: { n:"BrtEndPCDCalcMems", f:parsenoop },
22902 0x01B1: { n:"BrtBeginPCDCalcMem", f:parsenoop },
22903 0x01B2: { n:"BrtEndPCDCalcMem", f:parsenoop },
22904 0x01B3: { n:"BrtBeginPCDHGLevels", f:parsenoop },
22905 0x01B4: { n:"BrtEndPCDHGLevels", f:parsenoop },
22906 0x01B5: { n:"BrtBeginPCDHGLevel", f:parsenoop },
22907 0x01B6: { n:"BrtEndPCDHGLevel", f:parsenoop },
22908 0x01B7: { n:"BrtBeginPCDHGLGroups", f:parsenoop },
22909 0x01B8: { n:"BrtEndPCDHGLGroups", f:parsenoop },
22910 0x01B9: { n:"BrtBeginPCDHGLGroup", f:parsenoop },
22911 0x01BA: { n:"BrtEndPCDHGLGroup", f:parsenoop },
22912 0x01BB: { n:"BrtBeginPCDHGLGMembers", f:parsenoop },
22913 0x01BC: { n:"BrtEndPCDHGLGMembers", f:parsenoop },
22914 0x01BD: { n:"BrtBeginPCDHGLGMember", f:parsenoop },
22915 0x01BE: { n:"BrtEndPCDHGLGMember", f:parsenoop },
22916 0x01BF: { n:"BrtBeginQSI", f:parsenoop },
22917 0x01C0: { n:"BrtEndQSI", f:parsenoop },
22918 0x01C1: { n:"BrtBeginQSIR", f:parsenoop },
22919 0x01C2: { n:"BrtEndQSIR", f:parsenoop },
22920 0x01C3: { n:"BrtBeginDeletedNames", f:parsenoop },
22921 0x01C4: { n:"BrtEndDeletedNames", f:parsenoop },
22922 0x01C5: { n:"BrtBeginDeletedName", f:parsenoop },
22923 0x01C6: { n:"BrtEndDeletedName", f:parsenoop },
22924 0x01C7: { n:"BrtBeginQSIFs", f:parsenoop },
22925 0x01C8: { n:"BrtEndQSIFs", f:parsenoop },
22926 0x01C9: { n:"BrtBeginQSIF", f:parsenoop },
22927 0x01CA: { n:"BrtEndQSIF", f:parsenoop },
22928 0x01CB: { n:"BrtBeginAutoSortScope", f:parsenoop },
22929 0x01CC: { n:"BrtEndAutoSortScope", f:parsenoop },
22930 0x01CD: { n:"BrtBeginConditionalFormatting", f:parsenoop },
22931 0x01CE: { n:"BrtEndConditionalFormatting", f:parsenoop },
22932 0x01CF: { n:"BrtBeginCFRule", f:parsenoop },
22933 0x01D0: { n:"BrtEndCFRule", f:parsenoop },
22934 0x01D1: { n:"BrtBeginIconSet", f:parsenoop },
22935 0x01D2: { n:"BrtEndIconSet", f:parsenoop },
22936 0x01D3: { n:"BrtBeginDatabar", f:parsenoop },
22937 0x01D4: { n:"BrtEndDatabar", f:parsenoop },
22938 0x01D5: { n:"BrtBeginColorScale", f:parsenoop },
22939 0x01D6: { n:"BrtEndColorScale", f:parsenoop },
22940 0x01D7: { n:"BrtCFVO", f:parsenoop },
22941 0x01D8: { n:"BrtExternValueMeta", f:parsenoop },
22942 0x01D9: { n:"BrtBeginColorPalette", f:parsenoop },
22943 0x01DA: { n:"BrtEndColorPalette", f:parsenoop },
22944 0x01DB: { n:"BrtIndexedColor", f:parsenoop },
22945 0x01DC: { n:"BrtMargins", f:parsenoop },
22946 0x01DD: { n:"BrtPrintOptions", f:parsenoop },
22947 0x01DE: { n:"BrtPageSetup", f:parsenoop },
22948 0x01DF: { n:"BrtBeginHeaderFooter", f:parsenoop },
22949 0x01E0: { n:"BrtEndHeaderFooter", f:parsenoop },
22950 0x01E1: { n:"BrtBeginSXCrtFormat", f:parsenoop },
22951 0x01E2: { n:"BrtEndSXCrtFormat", f:parsenoop },
22952 0x01E3: { n:"BrtBeginSXCrtFormats", f:parsenoop },
22953 0x01E4: { n:"BrtEndSXCrtFormats", f:parsenoop },
22954 0x01E5: { n:"BrtWsFmtInfo", f:parsenoop },
22955 0x01E6: { n:"BrtBeginMgs", f:parsenoop },
22956 0x01E7: { n:"BrtEndMGs", f:parsenoop },
22957 0x01E8: { n:"BrtBeginMGMaps", f:parsenoop },
22958 0x01E9: { n:"BrtEndMGMaps", f:parsenoop },
22959 0x01EA: { n:"BrtBeginMG", f:parsenoop },
22960 0x01EB: { n:"BrtEndMG", f:parsenoop },
22961 0x01EC: { n:"BrtBeginMap", f:parsenoop },
22962 0x01ED: { n:"BrtEndMap", f:parsenoop },
22963 0x01EE: { n:"BrtHLink", f:parse_BrtHLink },
22964 0x01EF: { n:"BrtBeginDCon", f:parsenoop },
22965 0x01F0: { n:"BrtEndDCon", f:parsenoop },
22966 0x01F1: { n:"BrtBeginDRefs", f:parsenoop },
22967 0x01F2: { n:"BrtEndDRefs", f:parsenoop },
22968 0x01F3: { n:"BrtDRef", f:parsenoop },
22969 0x01F4: { n:"BrtBeginScenMan", f:parsenoop },
22970 0x01F5: { n:"BrtEndScenMan", f:parsenoop },
22971 0x01F6: { n:"BrtBeginSct", f:parsenoop },
22972 0x01F7: { n:"BrtEndSct", f:parsenoop },
22973 0x01F8: { n:"BrtSlc", f:parsenoop },
22974 0x01F9: { n:"BrtBeginDXFs", f:parsenoop },
22975 0x01FA: { n:"BrtEndDXFs", f:parsenoop },
22976 0x01FB: { n:"BrtDXF", f:parsenoop },
22977 0x01FC: { n:"BrtBeginTableStyles", f:parsenoop },
22978 0x01FD: { n:"BrtEndTableStyles", f:parsenoop },
22979 0x01FE: { n:"BrtBeginTableStyle", f:parsenoop },
22980 0x01FF: { n:"BrtEndTableStyle", f:parsenoop },
22981 0x0200: { n:"BrtTableStyleElement", f:parsenoop },
22982 0x0201: { n:"BrtTableStyleClient", f:parsenoop },
22983 0x0202: { n:"BrtBeginVolDeps", f:parsenoop },
22984 0x0203: { n:"BrtEndVolDeps", f:parsenoop },
22985 0x0204: { n:"BrtBeginVolType", f:parsenoop },
22986 0x0205: { n:"BrtEndVolType", f:parsenoop },
22987 0x0206: { n:"BrtBeginVolMain", f:parsenoop },
22988 0x0207: { n:"BrtEndVolMain", f:parsenoop },
22989 0x0208: { n:"BrtBeginVolTopic", f:parsenoop },
22990 0x0209: { n:"BrtEndVolTopic", f:parsenoop },
22991 0x020A: { n:"BrtVolSubtopic", f:parsenoop },
22992 0x020B: { n:"BrtVolRef", f:parsenoop },
22993 0x020C: { n:"BrtVolNum", f:parsenoop },
22994 0x020D: { n:"BrtVolErr", f:parsenoop },
22995 0x020E: { n:"BrtVolStr", f:parsenoop },
22996 0x020F: { n:"BrtVolBool", f:parsenoop },
22997 0x0210: { n:"BrtBeginCalcChain$", f:parsenoop },
22998 0x0211: { n:"BrtEndCalcChain$", f:parsenoop },
22999 0x0212: { n:"BrtBeginSortState", f:parsenoop },
23000 0x0213: { n:"BrtEndSortState", f:parsenoop },
23001 0x0214: { n:"BrtBeginSortCond", f:parsenoop },
23002 0x0215: { n:"BrtEndSortCond", f:parsenoop },
23003 0x0216: { n:"BrtBookProtection", f:parsenoop },
23004 0x0217: { n:"BrtSheetProtection", f:parsenoop },
23005 0x0218: { n:"BrtRangeProtection", f:parsenoop },
23006 0x0219: { n:"BrtPhoneticInfo", f:parsenoop },
23007 0x021A: { n:"BrtBeginECTxtWiz", f:parsenoop },
23008 0x021B: { n:"BrtEndECTxtWiz", f:parsenoop },
23009 0x021C: { n:"BrtBeginECTWFldInfoLst", f:parsenoop },
23010 0x021D: { n:"BrtEndECTWFldInfoLst", f:parsenoop },
23011 0x021E: { n:"BrtBeginECTwFldInfo", f:parsenoop },
23012 0x0224: { n:"BrtFileSharing", f:parsenoop },
23013 0x0225: { n:"BrtOleSize", f:parsenoop },
23014 0x0226: { n:"BrtDrawing", f:parsenoop },
23015 0x0227: { n:"BrtLegacyDrawing", f:parsenoop },
23016 0x0228: { n:"BrtLegacyDrawingHF", f:parsenoop },
23017 0x0229: { n:"BrtWebOpt", f:parsenoop },
23018 0x022A: { n:"BrtBeginWebPubItems", f:parsenoop },
23019 0x022B: { n:"BrtEndWebPubItems", f:parsenoop },
23020 0x022C: { n:"BrtBeginWebPubItem", f:parsenoop },
23021 0x022D: { n:"BrtEndWebPubItem", f:parsenoop },
23022 0x022E: { n:"BrtBeginSXCondFmt", f:parsenoop },
23023 0x022F: { n:"BrtEndSXCondFmt", f:parsenoop },
23024 0x0230: { n:"BrtBeginSXCondFmts", f:parsenoop },
23025 0x0231: { n:"BrtEndSXCondFmts", f:parsenoop },
23026 0x0232: { n:"BrtBkHim", f:parsenoop },
23027 0x0234: { n:"BrtColor", f:parsenoop },
23028 0x0235: { n:"BrtBeginIndexedColors", f:parsenoop },
23029 0x0236: { n:"BrtEndIndexedColors", f:parsenoop },
23030 0x0239: { n:"BrtBeginMRUColors", f:parsenoop },
23031 0x023A: { n:"BrtEndMRUColors", f:parsenoop },
23032 0x023C: { n:"BrtMRUColor", f:parsenoop },
23033 0x023D: { n:"BrtBeginDVals", f:parsenoop },
23034 0x023E: { n:"BrtEndDVals", f:parsenoop },
23035 0x0241: { n:"BrtSupNameStart", f:parsenoop },
23036 0x0242: { n:"BrtSupNameValueStart", f:parsenoop },
23037 0x0243: { n:"BrtSupNameValueEnd", f:parsenoop },
23038 0x0244: { n:"BrtSupNameNum", f:parsenoop },
23039 0x0245: { n:"BrtSupNameErr", f:parsenoop },
23040 0x0246: { n:"BrtSupNameSt", f:parsenoop },
23041 0x0247: { n:"BrtSupNameNil", f:parsenoop },
23042 0x0248: { n:"BrtSupNameBool", f:parsenoop },
23043 0x0249: { n:"BrtSupNameFmla", f:parsenoop },
23044 0x024A: { n:"BrtSupNameBits", f:parsenoop },
23045 0x024B: { n:"BrtSupNameEnd", f:parsenoop },
23046 0x024C: { n:"BrtEndSupBook", f:parsenoop },
23047 0x024D: { n:"BrtCellSmartTagProperty", f:parsenoop },
23048 0x024E: { n:"BrtBeginCellSmartTag", f:parsenoop },
23049 0x024F: { n:"BrtEndCellSmartTag", f:parsenoop },
23050 0x0250: { n:"BrtBeginCellSmartTags", f:parsenoop },
23051 0x0251: { n:"BrtEndCellSmartTags", f:parsenoop },
23052 0x0252: { n:"BrtBeginSmartTags", f:parsenoop },
23053 0x0253: { n:"BrtEndSmartTags", f:parsenoop },
23054 0x0254: { n:"BrtSmartTagType", f:parsenoop },
23055 0x0255: { n:"BrtBeginSmartTagTypes", f:parsenoop },
23056 0x0256: { n:"BrtEndSmartTagTypes", f:parsenoop },
23057 0x0257: { n:"BrtBeginSXFilters", f:parsenoop },
23058 0x0258: { n:"BrtEndSXFilters", f:parsenoop },
23059 0x0259: { n:"BrtBeginSXFILTER", f:parsenoop },
23060 0x025A: { n:"BrtEndSXFilter", f:parsenoop },
23061 0x025B: { n:"BrtBeginFills", f:parsenoop },
23062 0x025C: { n:"BrtEndFills", f:parsenoop },
23063 0x025D: { n:"BrtBeginCellWatches", f:parsenoop },
23064 0x025E: { n:"BrtEndCellWatches", f:parsenoop },
23065 0x025F: { n:"BrtCellWatch", f:parsenoop },
23066 0x0260: { n:"BrtBeginCRErrs", f:parsenoop },
23067 0x0261: { n:"BrtEndCRErrs", f:parsenoop },
23068 0x0262: { n:"BrtCrashRecErr", f:parsenoop },
23069 0x0263: { n:"BrtBeginFonts", f:parsenoop },
23070 0x0264: { n:"BrtEndFonts", f:parsenoop },
23071 0x0265: { n:"BrtBeginBorders", f:parsenoop },
23072 0x0266: { n:"BrtEndBorders", f:parsenoop },
23073 0x0267: { n:"BrtBeginFmts", f:parsenoop },
23074 0x0268: { n:"BrtEndFmts", f:parsenoop },
23075 0x0269: { n:"BrtBeginCellXFs", f:parsenoop },
23076 0x026A: { n:"BrtEndCellXFs", f:parsenoop },
23077 0x026B: { n:"BrtBeginStyles", f:parsenoop },
23078 0x026C: { n:"BrtEndStyles", f:parsenoop },
23079 0x0271: { n:"BrtBigName", f:parsenoop },
23080 0x0272: { n:"BrtBeginCellStyleXFs", f:parsenoop },
23081 0x0273: { n:"BrtEndCellStyleXFs", f:parsenoop },
23082 0x0274: { n:"BrtBeginComments", f:parsenoop },
23083 0x0275: { n:"BrtEndComments", f:parsenoop },
23084 0x0276: { n:"BrtBeginCommentAuthors", f:parsenoop },
23085 0x0277: { n:"BrtEndCommentAuthors", f:parsenoop },
23086 0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
23087 0x0279: { n:"BrtBeginCommentList", f:parsenoop },
23088 0x027A: { n:"BrtEndCommentList", f:parsenoop },
23089 0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment},
23090 0x027C: { n:"BrtEndComment", f:parsenoop },
23091 0x027D: { n:"BrtCommentText", f:parse_BrtCommentText },
23092 0x027E: { n:"BrtBeginOleObjects", f:parsenoop },
23093 0x027F: { n:"BrtOleObject", f:parsenoop },
23094 0x0280: { n:"BrtEndOleObjects", f:parsenoop },
23095 0x0281: { n:"BrtBeginSxrules", f:parsenoop },
23096 0x0282: { n:"BrtEndSxRules", f:parsenoop },
23097 0x0283: { n:"BrtBeginActiveXControls", f:parsenoop },
23098 0x0284: { n:"BrtActiveX", f:parsenoop },
23099 0x0285: { n:"BrtEndActiveXControls", f:parsenoop },
23100 0x0286: { n:"BrtBeginPCDSDTCEMembersSortBy", f:parsenoop },
23101 0x0288: { n:"BrtBeginCellIgnoreECs", f:parsenoop },
23102 0x0289: { n:"BrtCellIgnoreEC", f:parsenoop },
23103 0x028A: { n:"BrtEndCellIgnoreECs", f:parsenoop },
23104 0x028B: { n:"BrtCsProp", f:parsenoop },
23105 0x028C: { n:"BrtCsPageSetup", f:parsenoop },
23106 0x028D: { n:"BrtBeginUserCsViews", f:parsenoop },
23107 0x028E: { n:"BrtEndUserCsViews", f:parsenoop },
23108 0x028F: { n:"BrtBeginUserCsView", f:parsenoop },
23109 0x0290: { n:"BrtEndUserCsView", f:parsenoop },
23110 0x0291: { n:"BrtBeginPcdSFCIEntries", f:parsenoop },
23111 0x0292: { n:"BrtEndPCDSFCIEntries", f:parsenoop },
23112 0x0293: { n:"BrtPCDSFCIEntry", f:parsenoop },
23113 0x0294: { n:"BrtBeginListParts", f:parsenoop },
23114 0x0295: { n:"BrtListPart", f:parsenoop },
23115 0x0296: { n:"BrtEndListParts", f:parsenoop },
23116 0x0297: { n:"BrtSheetCalcProp", f:parsenoop },
23117 0x0298: { n:"BrtBeginFnGroup", f:parsenoop },
23118 0x0299: { n:"BrtFnGroup", f:parsenoop },
23119 0x029A: { n:"BrtEndFnGroup", f:parsenoop },
23120 0x029B: { n:"BrtSupAddin", f:parsenoop },
23121 0x029C: { n:"BrtSXTDMPOrder", f:parsenoop },
23122 0x029D: { n:"BrtCsProtection", f:parsenoop },
23123 0x029F: { n:"BrtBeginWsSortMap", f:parsenoop },
23124 0x02A0: { n:"BrtEndWsSortMap", f:parsenoop },
23125 0x02A1: { n:"BrtBeginRRSort", f:parsenoop },
23126 0x02A2: { n:"BrtEndRRSort", f:parsenoop },
23127 0x02A3: { n:"BrtRRSortItem", f:parsenoop },
23128 0x02A4: { n:"BrtFileSharingIso", f:parsenoop },
23129 0x02A5: { n:"BrtBookProtectionIso", f:parsenoop },
23130 0x02A6: { n:"BrtSheetProtectionIso", f:parsenoop },
23131 0x02A7: { n:"BrtCsProtectionIso", f:parsenoop },
23132 0x02A8: { n:"BrtRangeProtectionIso", f:parsenoop },
23133 0x0400: { n:"BrtRwDescent", f:parsenoop },
23134 0x0401: { n:"BrtKnownFonts", f:parsenoop },
23135 0x0402: { n:"BrtBeginSXTupleSet", f:parsenoop },
23136 0x0403: { n:"BrtEndSXTupleSet", f:parsenoop },
23137 0x0404: { n:"BrtBeginSXTupleSetHeader", f:parsenoop },
23138 0x0405: { n:"BrtEndSXTupleSetHeader", f:parsenoop },
23139 0x0406: { n:"BrtSXTupleSetHeaderItem", f:parsenoop },
23140 0x0407: { n:"BrtBeginSXTupleSetData", f:parsenoop },
23141 0x0408: { n:"BrtEndSXTupleSetData", f:parsenoop },
23142 0x0409: { n:"BrtBeginSXTupleSetRow", f:parsenoop },
23143 0x040A: { n:"BrtEndSXTupleSetRow", f:parsenoop },
23144 0x040B: { n:"BrtSXTupleSetRowItem", f:parsenoop },
23145 0x040C: { n:"BrtNameExt", f:parsenoop },
23146 0x040D: { n:"BrtPCDH14", f:parsenoop },
23147 0x040E: { n:"BrtBeginPCDCalcMem14", f:parsenoop },
23148 0x040F: { n:"BrtEndPCDCalcMem14", f:parsenoop },
23149 0x0410: { n:"BrtSXTH14", f:parsenoop },
23150 0x0411: { n:"BrtBeginSparklineGroup", f:parsenoop },
23151 0x0412: { n:"BrtEndSparklineGroup", f:parsenoop },
23152 0x0413: { n:"BrtSparkline", f:parsenoop },
23153 0x0414: { n:"BrtSXDI14", f:parsenoop },
23154 0x0415: { n:"BrtWsFmtInfoEx14", f:parsenoop },
23155 0x0416: { n:"BrtBeginConditionalFormatting14", f:parsenoop },
23156 0x0417: { n:"BrtEndConditionalFormatting14", f:parsenoop },
23157 0x0418: { n:"BrtBeginCFRule14", f:parsenoop },
23158 0x0419: { n:"BrtEndCFRule14", f:parsenoop },
23159 0x041A: { n:"BrtCFVO14", f:parsenoop },
23160 0x041B: { n:"BrtBeginDatabar14", f:parsenoop },
23161 0x041C: { n:"BrtBeginIconSet14", f:parsenoop },
23162 0x041D: { n:"BrtDVal14", f:parsenoop },
23163 0x041E: { n:"BrtBeginDVals14", f:parsenoop },
23164 0x041F: { n:"BrtColor14", f:parsenoop },
23165 0x0420: { n:"BrtBeginSparklines", f:parsenoop },
23166 0x0421: { n:"BrtEndSparklines", f:parsenoop },
23167 0x0422: { n:"BrtBeginSparklineGroups", f:parsenoop },
23168 0x0423: { n:"BrtEndSparklineGroups", f:parsenoop },
23169 0x0425: { n:"BrtSXVD14", f:parsenoop },
23170 0x0426: { n:"BrtBeginSxview14", f:parsenoop },
23171 0x0427: { n:"BrtEndSxview14", f:parsenoop },
23172 0x042A: { n:"BrtBeginPCD14", f:parsenoop },
23173 0x042B: { n:"BrtEndPCD14", f:parsenoop },
23174 0x042C: { n:"BrtBeginExtConn14", f:parsenoop },
23175 0x042D: { n:"BrtEndExtConn14", f:parsenoop },
23176 0x042E: { n:"BrtBeginSlicerCacheIDs", f:parsenoop },
23177 0x042F: { n:"BrtEndSlicerCacheIDs", f:parsenoop },
23178 0x0430: { n:"BrtBeginSlicerCacheID", f:parsenoop },
23179 0x0431: { n:"BrtEndSlicerCacheID", f:parsenoop },
23180 0x0433: { n:"BrtBeginSlicerCache", f:parsenoop },
23181 0x0434: { n:"BrtEndSlicerCache", f:parsenoop },
23182 0x0435: { n:"BrtBeginSlicerCacheDef", f:parsenoop },
23183 0x0436: { n:"BrtEndSlicerCacheDef", f:parsenoop },
23184 0x0437: { n:"BrtBeginSlicersEx", f:parsenoop },
23185 0x0438: { n:"BrtEndSlicersEx", f:parsenoop },
23186 0x0439: { n:"BrtBeginSlicerEx", f:parsenoop },
23187 0x043A: { n:"BrtEndSlicerEx", f:parsenoop },
23188 0x043B: { n:"BrtBeginSlicer", f:parsenoop },
23189 0x043C: { n:"BrtEndSlicer", f:parsenoop },
23190 0x043D: { n:"BrtSlicerCachePivotTables", f:parsenoop },
23191 0x043E: { n:"BrtBeginSlicerCacheOlapImpl", f:parsenoop },
23192 0x043F: { n:"BrtEndSlicerCacheOlapImpl", f:parsenoop },
23193 0x0440: { n:"BrtBeginSlicerCacheLevelsData", f:parsenoop },
23194 0x0441: { n:"BrtEndSlicerCacheLevelsData", f:parsenoop },
23195 0x0442: { n:"BrtBeginSlicerCacheLevelData", f:parsenoop },
23196 0x0443: { n:"BrtEndSlicerCacheLevelData", f:parsenoop },
23197 0x0444: { n:"BrtBeginSlicerCacheSiRanges", f:parsenoop },
23198 0x0445: { n:"BrtEndSlicerCacheSiRanges", f:parsenoop },
23199 0x0446: { n:"BrtBeginSlicerCacheSiRange", f:parsenoop },
23200 0x0447: { n:"BrtEndSlicerCacheSiRange", f:parsenoop },
23201 0x0448: { n:"BrtSlicerCacheOlapItem", f:parsenoop },
23202 0x0449: { n:"BrtBeginSlicerCacheSelections", f:parsenoop },
23203 0x044A: { n:"BrtSlicerCacheSelection", f:parsenoop },
23204 0x044B: { n:"BrtEndSlicerCacheSelections", f:parsenoop },
23205 0x044C: { n:"BrtBeginSlicerCacheNative", f:parsenoop },
23206 0x044D: { n:"BrtEndSlicerCacheNative", f:parsenoop },
23207 0x044E: { n:"BrtSlicerCacheNativeItem", f:parsenoop },
23208 0x044F: { n:"BrtRangeProtection14", f:parsenoop },
23209 0x0450: { n:"BrtRangeProtectionIso14", f:parsenoop },
23210 0x0451: { n:"BrtCellIgnoreEC14", f:parsenoop },
23211 0x0457: { n:"BrtList14", f:parsenoop },
23212 0x0458: { n:"BrtCFIcon", f:parsenoop },
23213 0x0459: { n:"BrtBeginSlicerCachesPivotCacheIDs", f:parsenoop },
23214 0x045A: { n:"BrtEndSlicerCachesPivotCacheIDs", f:parsenoop },
23215 0x045B: { n:"BrtBeginSlicers", f:parsenoop },
23216 0x045C: { n:"BrtEndSlicers", f:parsenoop },
23217 0x045D: { n:"BrtWbProp14", f:parsenoop },
23218 0x045E: { n:"BrtBeginSXEdit", f:parsenoop },
23219 0x045F: { n:"BrtEndSXEdit", f:parsenoop },
23220 0x0460: { n:"BrtBeginSXEdits", f:parsenoop },
23221 0x0461: { n:"BrtEndSXEdits", f:parsenoop },
23222 0x0462: { n:"BrtBeginSXChange", f:parsenoop },
23223 0x0463: { n:"BrtEndSXChange", f:parsenoop },
23224 0x0464: { n:"BrtBeginSXChanges", f:parsenoop },
23225 0x0465: { n:"BrtEndSXChanges", f:parsenoop },
23226 0x0466: { n:"BrtSXTupleItems", f:parsenoop },
23227 0x0468: { n:"BrtBeginSlicerStyle", f:parsenoop },
23228 0x0469: { n:"BrtEndSlicerStyle", f:parsenoop },
23229 0x046A: { n:"BrtSlicerStyleElement", f:parsenoop },
23230 0x046B: { n:"BrtBeginStyleSheetExt14", f:parsenoop },
23231 0x046C: { n:"BrtEndStyleSheetExt14", f:parsenoop },
23232 0x046D: { n:"BrtBeginSlicerCachesPivotCacheID", f:parsenoop },
23233 0x046E: { n:"BrtEndSlicerCachesPivotCacheID", f:parsenoop },
23234 0x046F: { n:"BrtBeginConditionalFormattings", f:parsenoop },
23235 0x0470: { n:"BrtEndConditionalFormattings", f:parsenoop },
23236 0x0471: { n:"BrtBeginPCDCalcMemExt", f:parsenoop },
23237 0x0472: { n:"BrtEndPCDCalcMemExt", f:parsenoop },
23238 0x0473: { n:"BrtBeginPCDCalcMemsExt", f:parsenoop },
23239 0x0474: { n:"BrtEndPCDCalcMemsExt", f:parsenoop },
23240 0x0475: { n:"BrtPCDField14", f:parsenoop },
23241 0x0476: { n:"BrtBeginSlicerStyles", f:parsenoop },
23242 0x0477: { n:"BrtEndSlicerStyles", f:parsenoop },
23243 0x0478: { n:"BrtBeginSlicerStyleElements", f:parsenoop },
23244 0x0479: { n:"BrtEndSlicerStyleElements", f:parsenoop },
23245 0x047A: { n:"BrtCFRuleExt", f:parsenoop },
23246 0x047B: { n:"BrtBeginSXCondFmt14", f:parsenoop },
23247 0x047C: { n:"BrtEndSXCondFmt14", f:parsenoop },
23248 0x047D: { n:"BrtBeginSXCondFmts14", f:parsenoop },
23249 0x047E: { n:"BrtEndSXCondFmts14", f:parsenoop },
23250 0x0480: { n:"BrtBeginSortCond14", f:parsenoop },
23251 0x0481: { n:"BrtEndSortCond14", f:parsenoop },
23252 0x0482: { n:"BrtEndDVals14", f:parsenoop },
23253 0x0483: { n:"BrtEndIconSet14", f:parsenoop },
23254 0x0484: { n:"BrtEndDatabar14", f:parsenoop },
23255 0x0485: { n:"BrtBeginColorScale14", f:parsenoop },
23256 0x0486: { n:"BrtEndColorScale14", f:parsenoop },
23257 0x0487: { n:"BrtBeginSxrules14", f:parsenoop },
23258 0x0488: { n:"BrtEndSxrules14", f:parsenoop },
23259 0x0489: { n:"BrtBeginPRule14", f:parsenoop },
23260 0x048A: { n:"BrtEndPRule14", f:parsenoop },
23261 0x048B: { n:"BrtBeginPRFilters14", f:parsenoop },
23262 0x048C: { n:"BrtEndPRFilters14", f:parsenoop },
23263 0x048D: { n:"BrtBeginPRFilter14", f:parsenoop },
23264 0x048E: { n:"BrtEndPRFilter14", f:parsenoop },
23265 0x048F: { n:"BrtBeginPRFItem14", f:parsenoop },
23266 0x0490: { n:"BrtEndPRFItem14", f:parsenoop },
23267 0x0491: { n:"BrtBeginCellIgnoreECs14", f:parsenoop },
23268 0x0492: { n:"BrtEndCellIgnoreECs14", f:parsenoop },
23269 0x0493: { n:"BrtDxf14", f:parsenoop },
23270 0x0494: { n:"BrtBeginDxF14s", f:parsenoop },
23271 0x0495: { n:"BrtEndDxf14s", f:parsenoop },
23272 0x0499: { n:"BrtFilter14", f:parsenoop },
23273 0x049A: { n:"BrtBeginCustomFilters14", f:parsenoop },
23274 0x049C: { n:"BrtCustomFilter14", f:parsenoop },
23275 0x049D: { n:"BrtIconFilter14", f:parsenoop },
23276 0x049E: { n:"BrtPivotCacheConnectionName", f:parsenoop },
23277 0x0800: { n:"BrtBeginDecoupledPivotCacheIDs", f:parsenoop },
23278 0x0801: { n:"BrtEndDecoupledPivotCacheIDs", f:parsenoop },
23279 0x0802: { n:"BrtDecoupledPivotCacheID", f:parsenoop },
23280 0x0803: { n:"BrtBeginPivotTableRefs", f:parsenoop },
23281 0x0804: { n:"BrtEndPivotTableRefs", f:parsenoop },
23282 0x0805: { n:"BrtPivotTableRef", f:parsenoop },
23283 0x0806: { n:"BrtSlicerCacheBookPivotTables", f:parsenoop },
23284 0x0807: { n:"BrtBeginSxvcells", f:parsenoop },
23285 0x0808: { n:"BrtEndSxvcells", f:parsenoop },
23286 0x0809: { n:"BrtBeginSxRow", f:parsenoop },
23287 0x080A: { n:"BrtEndSxRow", f:parsenoop },
23288 0x080C: { n:"BrtPcdCalcMem15", f:parsenoop },
23289 0x0813: { n:"BrtQsi15", f:parsenoop },
23290 0x0814: { n:"BrtBeginWebExtensions", f:parsenoop },
23291 0x0815: { n:"BrtEndWebExtensions", f:parsenoop },
23292 0x0816: { n:"BrtWebExtension", f:parsenoop },
23293 0x0817: { n:"BrtAbsPath15", f:parsenoop },
23294 0x0818: { n:"BrtBeginPivotTableUISettings", f:parsenoop },
23295 0x0819: { n:"BrtEndPivotTableUISettings", f:parsenoop },
23296 0x081B: { n:"BrtTableSlicerCacheIDs", f:parsenoop },
23297 0x081C: { n:"BrtTableSlicerCacheID", f:parsenoop },
23298 0x081D: { n:"BrtBeginTableSlicerCache", f:parsenoop },
23299 0x081E: { n:"BrtEndTableSlicerCache", f:parsenoop },
23300 0x081F: { n:"BrtSxFilter15", f:parsenoop },
23301 0x0820: { n:"BrtBeginTimelineCachePivotCacheIDs", f:parsenoop },
23302 0x0821: { n:"BrtEndTimelineCachePivotCacheIDs", f:parsenoop },
23303 0x0822: { n:"BrtTimelineCachePivotCacheID", f:parsenoop },
23304 0x0823: { n:"BrtBeginTimelineCacheIDs", f:parsenoop },
23305 0x0824: { n:"BrtEndTimelineCacheIDs", f:parsenoop },
23306 0x0825: { n:"BrtBeginTimelineCacheID", f:parsenoop },
23307 0x0826: { n:"BrtEndTimelineCacheID", f:parsenoop },
23308 0x0827: { n:"BrtBeginTimelinesEx", f:parsenoop },
23309 0x0828: { n:"BrtEndTimelinesEx", f:parsenoop },
23310 0x0829: { n:"BrtBeginTimelineEx", f:parsenoop },
23311 0x082A: { n:"BrtEndTimelineEx", f:parsenoop },
23312 0x082B: { n:"BrtWorkBookPr15", f:parsenoop },
23313 0x082C: { n:"BrtPCDH15", f:parsenoop },
23314 0x082D: { n:"BrtBeginTimelineStyle", f:parsenoop },
23315 0x082E: { n:"BrtEndTimelineStyle", f:parsenoop },
23316 0x082F: { n:"BrtTimelineStyleElement", f:parsenoop },
23317 0x0830: { n:"BrtBeginTimelineStylesheetExt15", f:parsenoop },
23318 0x0831: { n:"BrtEndTimelineStylesheetExt15", f:parsenoop },
23319 0x0832: { n:"BrtBeginTimelineStyles", f:parsenoop },
23320 0x0833: { n:"BrtEndTimelineStyles", f:parsenoop },
23321 0x0834: { n:"BrtBeginTimelineStyleElements", f:parsenoop },
23322 0x0835: { n:"BrtEndTimelineStyleElements", f:parsenoop },
23323 0x0836: { n:"BrtDxf15", f:parsenoop },
23324 0x0837: { n:"BrtBeginDxfs15", f:parsenoop },
23325 0x0838: { n:"brtEndDxfs15", f:parsenoop },
23326 0x0839: { n:"BrtSlicerCacheHideItemsWithNoData", f:parsenoop },
23327 0x083A: { n:"BrtBeginItemUniqueNames", f:parsenoop },
23328 0x083B: { n:"BrtEndItemUniqueNames", f:parsenoop },
23329 0x083C: { n:"BrtItemUniqueName", f:parsenoop },
23330 0x083D: { n:"BrtBeginExtConn15", f:parsenoop },
23331 0x083E: { n:"BrtEndExtConn15", f:parsenoop },
23332 0x083F: { n:"BrtBeginOledbPr15", f:parsenoop },
23333 0x0840: { n:"BrtEndOledbPr15", f:parsenoop },
23334 0x0841: { n:"BrtBeginDataFeedPr15", f:parsenoop },
23335 0x0842: { n:"BrtEndDataFeedPr15", f:parsenoop },
23336 0x0843: { n:"BrtTextPr15", f:parsenoop },
23337 0x0844: { n:"BrtRangePr15", f:parsenoop },
23338 0x0845: { n:"BrtDbCommand15", f:parsenoop },
23339 0x0846: { n:"BrtBeginDbTables15", f:parsenoop },
23340 0x0847: { n:"BrtEndDbTables15", f:parsenoop },
23341 0x0848: { n:"BrtDbTable15", f:parsenoop },
23342 0x0849: { n:"BrtBeginDataModel", f:parsenoop },
23343 0x084A: { n:"BrtEndDataModel", f:parsenoop },
23344 0x084B: { n:"BrtBeginModelTables", f:parsenoop },
23345 0x084C: { n:"BrtEndModelTables", f:parsenoop },
23346 0x084D: { n:"BrtModelTable", f:parsenoop },
23347 0x084E: { n:"BrtBeginModelRelationships", f:parsenoop },
23348 0x084F: { n:"BrtEndModelRelationships", f:parsenoop },
23349 0x0850: { n:"BrtModelRelationship", f:parsenoop },
23350 0x0851: { n:"BrtBeginECTxtWiz15", f:parsenoop },
23351 0x0852: { n:"BrtEndECTxtWiz15", f:parsenoop },
23352 0x0853: { n:"BrtBeginECTWFldInfoLst15", f:parsenoop },
23353 0x0854: { n:"BrtEndECTWFldInfoLst15", f:parsenoop },
23354 0x0855: { n:"BrtBeginECTWFldInfo15", f:parsenoop },
23355 0x0856: { n:"BrtFieldListActiveItem", f:parsenoop },
23356 0x0857: { n:"BrtPivotCacheIdVersion", f:parsenoop },
23357 0x0858: { n:"BrtSXDI15", f:parsenoop },
23358 0xFFFF: { n:"", f:parsenoop }
23359 };
23360
23361 var evert_RE = evert_key(RecordEnum, 'n');
23362 function fix_opts_func(defaults) {
23363 return function fix_opts(opts) {
23364 for(var i = 0; i != defaults.length; ++i) {
23365 var d = defaults[i];
23366 if(opts[d[0]] === undefined) opts[d[0]] = d[1];
23367 if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
23368 }
23369 };
23370 }
23371
23372 var fix_read_opts = fix_opts_func([
23373 ['cellNF', false], /* emit cell number format string as .z */
23374 ['cellHTML', true], /* emit html string as .h */
23375 ['cellFormula', true], /* emit formulae as .f */
23376 ['cellStyles', false], /* emits style/theme as .s */
23377
23378 ['sheetStubs', false], /* emit empty cells */
23379 ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
23380
23381 ['bookDeps', false], /* parse calculation chains */
23382 ['bookSheets', false], /* only try to get sheet names (no Sheets) */
23383 ['bookProps', false], /* only try to get properties (no Sheets) */
23384 ['bookFiles', false], /* include raw file structure (keys, files) */
23385 ['bookVBA', false], /* include vba raw data (vbaraw) */
23386
23387 ['WTF', false] /* WTF mode (throws errors) */
23388 ]);
23389
23390
23391 var fix_write_opts = fix_opts_func([
23392 ['bookSST', false], /* Generate Shared String Table */
23393
23394 ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
23395
23396 ['WTF', false] /* WTF mode (throws errors) */
23397 ]);
23398 function safe_parse_wbrels(wbrels, sheets) {
23399 if(!wbrels) return 0;
23400 try {
23401 wbrels = sheets.map(function pwbr(w) { return [w.name, wbrels['!id'][w.id].Target]; });
23402 } catch(e) { return null; }
23403 return !wbrels || wbrels.length === 0 ? null : wbrels;
23404 }
23405
23406 function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts) {
23407 try {
23408 sheetRels[sheet]=parse_rels(getzipdata(zip, relsPath, true), path);
23409 sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet]);
23410 } catch(e) { if(opts.WTF) throw e; }
23411 }
23412
23413 var nodirs = function nodirs(x){return x.substr(-1) != '/';};
23414 function parse_zip(zip, opts) {
23415 make_ssf(SSF);
23416 opts = opts || {};
23417 fix_read_opts(opts);
23418 reset_cp();
23419 var entries = keys(zip.files).filter(nodirs).sort();
23420 var dir = parse_ct(getzipdata(zip, '[Content_Types].xml'), opts);
23421 var xlsb = false;
23422 var sheets, binname;
23423 if(dir.workbooks.length === 0) {
23424 binname = "xl/workbook.xml";
23425 if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
23426 }
23427 if(dir.workbooks.length === 0) {
23428 binname = "xl/workbook.bin";
23429 if(!getzipfile(zip,binname,true)) throw new Error("Could not find workbook");
23430 dir.workbooks.push(binname);
23431 xlsb = true;
23432 }
23433 if(dir.workbooks[0].substr(-3) == "bin") xlsb = true;
23434 if(xlsb) set_cp(1200);
23435
23436 if(!opts.bookSheets && !opts.bookProps) {
23437 strs = [];
23438 if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);
23439
23440 styles = {};
23441 if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
23442
23443 themes = {};
23444 if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,''), true),dir.themes[0], opts);
23445 }
23446
23447 var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
23448
23449 var props = {}, propdata = "";
23450
23451 if(dir.coreprops.length !== 0) {
23452 propdata = getzipdata(zip, dir.coreprops[0].replace(/^\//,''), true);
23453 if(propdata) props = parse_core_props(propdata);
23454 if(dir.extprops.length !== 0) {
23455 propdata = getzipdata(zip, dir.extprops[0].replace(/^\//,''), true);
23456 if(propdata) parse_ext_props(propdata, props);
23457 }
23458 }
23459
23460 var custprops = {};
23461 if(!opts.bookSheets || opts.bookProps) {
23462 if (dir.custprops.length !== 0) {
23463 propdata = getzipdata(zip, dir.custprops[0].replace(/^\//,''), true);
23464 if(propdata) custprops = parse_cust_props(propdata, opts);
23465 }
23466 }
23467
23468 var out = {};
23469 if(opts.bookSheets || opts.bookProps) {
23470 if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
23471 else if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
23472 if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
23473 if(typeof sheets !== 'undefined') out.SheetNames = sheets;
23474 if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
23475 }
23476 sheets = {};
23477
23478 var deps = {};
23479 if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts);
23480
23481 var i=0;
23482 var sheetRels = {};
23483 var path, relsPath;
23484 if(!props.Worksheets) {
23485 var wbsheets = wb.Sheets;
23486 props.Worksheets = wbsheets.length;
23487 props.SheetNames = [];
23488 for(var j = 0; j != wbsheets.length; ++j) {
23489 props.SheetNames[j] = wbsheets[j].name;
23490 }
23491 }
23492
23493 var wbext = xlsb ? "bin" : "xml";
23494 var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
23495 var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
23496 if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
23497 /* Numbers iOS hack */
23498 var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
23499 for(i = 0; i != props.Worksheets; ++i) {
23500 if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
23501 else {
23502 path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
23503 path = path.replace(/sheet0\./,"sheet.");
23504 }
23505 relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
23506 safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts);
23507 }
23508
23509 if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
23510
23511 out = {
23512 Directory: dir,
23513 Workbook: wb,
23514 Props: props,
23515 Custprops: custprops,
23516 Deps: deps,
23517 Sheets: sheets,
23518 SheetNames: props.SheetNames,
23519 Strings: strs,
23520 Styles: styles,
23521 Themes: themes,
23522 SSF: SSF.get_table()
23523 };
23524 if(opts.bookFiles) {
23525 out.keys = entries;
23526 out.files = zip.files;
23527 }
23528 if(opts.bookVBA) {
23529 if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,dir.vba[0],true);
23530 else if(dir.defaults.bin === 'application/vnd.ms-office.vbaProject') out.vbaraw = getzipdata(zip,'xl/vbaProject.bin',true);
23531 }
23532 return out;
23533 }
23534 function add_rels(rels, rId, f, type, relobj) {
23535 if(!relobj) relobj = {};
23536 if(!rels['!id']) rels['!id'] = {};
23537 relobj.Id = 'rId' + rId;
23538 relobj.Type = type;
23539 relobj.Target = f;
23540 if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
23541 rels['!id'][relobj.Id] = relobj;
23542 rels[('/' + relobj.Target).replace("//","/")] = relobj;
23543 }
23544
23545 function write_zip(wb, opts) {
23546 if(wb && !wb.SSF) {
23547 wb.SSF = SSF.get_table();
23548 }
23549 if(wb && wb.SSF) {
23550 make_ssf(SSF); SSF.load_table(wb.SSF);
23551 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
23552 }
23553 opts.rels = {}; opts.wbrels = {};
23554 opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
23555 var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
23556 var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
23557 coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
23558 TODO:[], rels:[], xmlns: "" };
23559 fix_write_opts(opts = opts || {});
23560 var zip = new jszip();
23561 var f = "", rId = 0;
23562
23563 opts.cellXfs = [];
23564 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
23565
23566 f = "docProps/core.xml";
23567 zip.file(f, write_core_props(wb.Props, opts));
23568 ct.coreprops.push(f);
23569 add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
23570
23571 f = "docProps/app.xml";
23572 if(!wb.Props) wb.Props = {};
23573 wb.Props.SheetNames = wb.SheetNames;
23574 wb.Props.Worksheets = wb.SheetNames.length;
23575 zip.file(f, write_ext_props(wb.Props, opts));
23576 ct.extprops.push(f);
23577 add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
23578
23579 if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
23580 f = "docProps/custom.xml";
23581 zip.file(f, write_cust_props(wb.Custprops, opts));
23582 ct.custprops.push(f);
23583 add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
23584 }
23585
23586 f = "xl/workbook." + wbext;
23587 zip.file(f, write_wb(wb, f, opts));
23588 ct.workbooks.push(f);
23589 add_rels(opts.rels, 1, f, RELS.WB);
23590
23591 for(rId=1;rId <= wb.SheetNames.length; ++rId) {
23592 f = "xl/worksheets/sheet" + rId + "." + wbext;
23593 zip.file(f, write_ws(rId-1, f, opts, wb));
23594 ct.sheets.push(f);
23595 add_rels(opts.wbrels, rId, "worksheets/sheet" + rId + "." + wbext, RELS.WS);
23596 }
23597
23598 if(opts.Strings != null && opts.Strings.length > 0) {
23599 f = "xl/sharedStrings." + wbext;
23600 zip.file(f, write_sst(opts.Strings, f, opts));
23601 ct.strs.push(f);
23602 add_rels(opts.wbrels, ++rId, "sharedStrings." + wbext, RELS.SST);
23603 }
23604
23605 /* TODO: something more intelligent with themes */
23606
23607 f = "xl/theme/theme1.xml";
23608 zip.file(f, write_theme());
23609 ct.themes.push(f);
23610 add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME);
23611
23612 /* TODO: something more intelligent with styles */
23613
23614 f = "xl/styles." + wbext;
23615 zip.file(f, write_sty(wb, f, opts));
23616 ct.styles.push(f);
23617 add_rels(opts.wbrels, ++rId, "styles." + wbext, RELS.STY);
23618
23619 zip.file("[Content_Types].xml", write_ct(ct, opts));
23620 zip.file('_rels/.rels', write_rels(opts.rels));
23621 zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
23622 return zip;
23623 }
23624 function readSync(data, opts) {
23625 var zip, d = data;
23626 var o = opts||{};
23627 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
23628 switch(o.type) {
23629 case "base64": zip = new jszip(d, { base64:true }); break;
23630 case "binary": zip = new jszip(d, { base64:false }); break;
23631 case "buffer": zip = new jszip(d); break;
23632 case "file": zip=new jszip(d=_fs.readFileSync(data)); break;
23633 default: throw new Error("Unrecognized type " + o.type);
23634 }
23635 return parse_zip(zip, o);
23636 }
23637
23638 function readFileSync(data, opts) {
23639 var o = opts||{}; o.type = 'file';
23640 return readSync(data, o);
23641 }
23642
23643 function writeSync(wb, opts) {
23644 var o = opts||{};
23645 var z = write_zip(wb, o);
23646 switch(o.type) {
23647 case "base64": return z.generate({type:"base64"});
23648 case "binary": return z.generate({type:"string"});
23649 case "buffer": return z.generate({type:"nodebuffer"});
23650 case "file": return _fs.writeFileSync(o.file, z.generate({type:"nodebuffer"}));
23651 default: throw new Error("Unrecognized type " + o.type);
23652 }
23653 }
23654
23655 function writeFileSync(wb, filename, opts) {
23656 var o = opts||{}; o.type = 'file';
23657 o.file = filename;
23658 switch(o.file.substr(-5).toLowerCase()) {
23659 case '.xlsm': o.bookType = 'xlsm'; break;
23660 case '.xlsb': o.bookType = 'xlsb'; break;
23661 }
23662 return writeSync(wb, o);
23663 }
23664
23665 function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; }
23666 function encode_row(row) { return "" + (row + 1); }
23667 function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
23668 function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); }
23669
23670 function decode_col(colstr) { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
23671 function encode_col(col) { var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
23672 function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); }
23673 function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); }
23674
23675 function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
23676 function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
23677 function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); }
23678 function fix_cell(cstr) { return fix_col(fix_row(cstr)); }
23679 function unfix_cell(cstr) { return unfix_col(unfix_row(cstr)); }
23680 function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
23681 function encode_range(cs,ce) {
23682 if(ce === undefined || typeof ce === 'number') return encode_range(cs.s, cs.e);
23683 if(typeof cs !== 'string') cs = encode_cell(cs); if(typeof ce !== 'string') ce = encode_cell(ce);
23684 return cs == ce ? cs : cs + ":" + ce;
23685 }
23686
23687 function safe_decode_range(range) {
23688 var o = {s:{c:0,r:0},e:{c:0,r:0}};
23689 var idx = 0, i = 0, cc = 0;
23690 var len = range.length;
23691 for(idx = 0; i < len; ++i) {
23692 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
23693 idx = 26*idx + cc;
23694 }
23695 o.s.c = --idx;
23696
23697 for(idx = 0; i < len; ++i) {
23698 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
23699 idx = 10*idx + cc;
23700 }
23701 o.s.r = --idx;
23702
23703 if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
23704
23705 for(idx = 0; i != len; ++i) {
23706 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
23707 idx = 26*idx + cc;
23708 }
23709 o.e.c = --idx;
23710
23711 for(idx = 0; i != len; ++i) {
23712 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
23713 idx = 10*idx + cc;
23714 }
23715 o.e.r = --idx;
23716 return o;
23717 }
23718
23719 function safe_format_cell(cell, v) {
23720 if(cell.z !== undefined) try { return (cell.w = SSF.format(cell.z, v)); } catch(e) { }
23721 if(!cell.XF) return v;
23722 try { return (cell.w = SSF.format(cell.XF.ifmt||0, v)); } catch(e) { return ''+v; }
23723 }
23724
23725 function format_cell(cell, v) {
23726 if(cell == null || cell.t == null) return "";
23727 if(cell.w !== undefined) return cell.w;
23728 if(v === undefined) return safe_format_cell(cell, cell.v);
23729 return safe_format_cell(cell, v);
23730 }
23731
23732 function sheet_to_json(sheet, opts){
23733 var val, row, range, header = 0, offset = 1, r, hdr = [], isempty, R, C, v;
23734 var o = opts != null ? opts : {};
23735 var raw = o.raw;
23736 if(sheet == null || sheet["!ref"] == null) return [];
23737 range = o.range !== undefined ? o.range : sheet["!ref"];
23738 if(o.header === 1) header = 1;
23739 else if(o.header === "A") header = 2;
23740 else if(Array.isArray(o.header)) header = 3;
23741 switch(typeof range) {
23742 case 'string': r = safe_decode_range(range); break;
23743 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
23744 default: r = range;
23745 }
23746 if(header > 0) offset = 0;
23747 var rr = encode_row(r.s.r);
23748 var cols = new Array(r.e.c-r.s.c+1);
23749 var out = new Array(r.e.r-r.s.r-offset+1);
23750 var outi = 0;
23751 for(C = r.s.c; C <= r.e.c; ++C) {
23752 cols[C] = encode_col(C);
23753 val = sheet[cols[C] + rr];
23754 switch(header) {
23755 case 1: hdr[C] = C; break;
23756 case 2: hdr[C] = cols[C]; break;
23757 case 3: hdr[C] = o.header[C - r.s.c]; break;
23758 default:
23759 if(val === undefined) continue;
23760 hdr[C] = format_cell(val);
23761 }
23762 }
23763
23764 for (R = r.s.r + offset; R <= r.e.r; ++R) {
23765 rr = encode_row(R);
23766 isempty = true;
23767 row = header === 1 ? [] : Object.create({ __rowNum__ : R });
23768 for (C = r.s.c; C <= r.e.c; ++C) {
23769 val = sheet[cols[C] + rr];
23770 if(val === undefined || val.t === undefined) continue;
23771 v = val.v;
23772 switch(val.t){
23773 case 'e': continue;
23774 case 's': case 'str': break;
23775 case 'b': case 'n': break;
23776 default: throw 'unrecognized type ' + val.t;
23777 }
23778 if(v !== undefined) {
23779 row[hdr[C]] = raw ? v : format_cell(val,v);
23780 isempty = false;
23781 }
23782 }
23783 if(isempty === false) out[outi++] = row;
23784 }
23785 out.length = outi;
23786 return out;
23787 }
23788
23789 function sheet_to_row_object_array(sheet, opts) { return sheet_to_json(sheet, opts != null ? opts : {}); }
23790
23791 function sheet_to_csv(sheet, opts) {
23792 var out = "", txt = "", qreg = /"/g;
23793 var o = opts == null ? {} : opts;
23794 if(sheet == null || sheet["!ref"] == null) return "";
23795 var r = safe_decode_range(sheet["!ref"]);
23796 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
23797 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
23798 var row = "", rr = "", cols = [];
23799 var i = 0, cc = 0, val;
23800 var R = 0, C = 0;
23801 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
23802 for(R = r.s.r; R <= r.e.r; ++R) {
23803 row = "";
23804 rr = encode_row(R);
23805 for(C = r.s.c; C <= r.e.c; ++C) {
23806 val = sheet[cols[C] + rr];
23807 txt = val !== undefined ? ''+format_cell(val) : "";
23808 for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
23809 txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
23810 row += (C === r.s.c ? "" : FS) + txt;
23811 }
23812 out += row + RS;
23813 }
23814 return out;
23815 }
23816 var make_csv = sheet_to_csv;
23817
23818 function sheet_to_formulae(sheet) {
23819 var cmds, y = "", x, val="";
23820 if(sheet == null || sheet["!ref"] == null) return "";
23821 var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
23822 cmds = new Array((r.e.r-r.s.r+1)*(r.e.c-r.s.c+1));
23823 var i = 0;
23824 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
23825 for(var R = r.s.r; R <= r.e.r; ++R) {
23826 rr = encode_row(R);
23827 for(C = r.s.c; C <= r.e.c; ++C) {
23828 y = cols[C] + rr;
23829 x = sheet[y];
23830 val = "";
23831 if(x === undefined) continue;
23832 if(x.f != null) val = x.f;
23833 else if(x.w !== undefined) val = "'" + x.w;
23834 else if(x.v === undefined) continue;
23835 else val = ""+x.v;
23836 cmds[i++] = y + "=" + val;
23837 }
23838 }
23839 cmds.length = i;
23840 return cmds;
23841 }
23842
23843 var utils = {
23844 encode_col: encode_col,
23845 encode_row: encode_row,
23846 encode_cell: encode_cell,
23847 encode_range: encode_range,
23848 decode_col: decode_col,
23849 decode_row: decode_row,
23850 split_cell: split_cell,
23851 decode_cell: decode_cell,
23852 decode_range: decode_range,
23853 format_cell: format_cell,
23854 get_formulae: sheet_to_formulae,
23855 make_csv: sheet_to_csv,
23856 make_json: sheet_to_json,
23857 make_formulae: sheet_to_formulae,
23858 sheet_to_csv: sheet_to_csv,
23859 sheet_to_json: sheet_to_json,
23860 sheet_to_formulae: sheet_to_formulae,
23861 sheet_to_row_object_array: sheet_to_row_object_array
23862 };
23863 XLSX.parseZip = parse_zip;
23864 XLSX.read = readSync;
23865 XLSX.readFile = readFileSync;
23866 XLSX.write = writeSync;
23867 XLSX.writeFile = writeFileSync;
23868 XLSX.utils = utils;
23869 XLSX.SSF = SSF;
23870 })(typeof exports !== 'undefined' ? exports : XLSX);
23871 //! moment.js
23872 //! version : 2.5.1
23873 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
23874 //! license : MIT
23875 //! momentjs.com
23876
23877 (function (undefined) {
23878
23879 /************************************
23880 Constants
23881 ************************************/
23882
23883 var moment,
23884 VERSION = "2.5.1",
23885 global = this,
23886 round = Math.round,
23887 i,
23888
23889 YEAR = 0,
23890 MONTH = 1,
23891 DATE = 2,
23892 HOUR = 3,
23893 MINUTE = 4,
23894 SECOND = 5,
23895 MILLISECOND = 6,
23896
23897 // internal storage for language config files
23898 languages = {},
23899
23900 // moment internal properties
23901 momentProperties = {
23902 _isAMomentObject: null,
23903 _i : null,
23904 _f : null,
23905 _l : null,
23906 _strict : null,
23907 _isUTC : null,
23908 _offset : null, // optional. Combine with _isUTC
23909 _pf : null,
23910 _lang : null // optional
23911 },
23912
23913 // check for nodeJS
23914 hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
23915
23916 // ASP.NET json date format regex
23917 aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
23918 aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
23919
23920 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
23921 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
23922 isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
23923
23924 // format tokens
23925 formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
23926 localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
23927
23928 // parsing token regexes
23929 parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
23930 parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
23931 parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
23932 parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
23933 parseTokenDigits = /\d+/, // nonzero number of digits
23934 parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
23935 parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
23936 parseTokenT = /T/i, // T (ISO separator)
23937 parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
23938
23939 //strict parsing regexes
23940 parseTokenOneDigit = /\d/, // 0 - 9
23941 parseTokenTwoDigits = /\d\d/, // 00 - 99
23942 parseTokenThreeDigits = /\d{3}/, // 000 - 999
23943 parseTokenFourDigits = /\d{4}/, // 0000 - 9999
23944 parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
23945 parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
23946
23947 // iso 8601 regex
23948 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
23949 isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
23950
23951 isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
23952
23953 isoDates = [
23954 ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
23955 ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
23956 ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
23957 ['GGGG-[W]WW', /\d{4}-W\d{2}/],
23958 ['YYYY-DDD', /\d{4}-\d{3}/]
23959 ],
23960
23961 // iso time formats and regexes
23962 isoTimes = [
23963 ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
23964 ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
23965 ['HH:mm', /(T| )\d\d:\d\d/],
23966 ['HH', /(T| )\d\d/]
23967 ],
23968
23969 // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
23970 parseTimezoneChunker = /([\+\-]|\d\d)/gi,
23971
23972 // getter and setter names
23973 proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
23974 unitMillisecondFactors = {
23975 'Milliseconds' : 1,
23976 'Seconds' : 1e3,
23977 'Minutes' : 6e4,
23978 'Hours' : 36e5,
23979 'Days' : 864e5,
23980 'Months' : 2592e6,
23981 'Years' : 31536e6
23982 },
23983
23984 unitAliases = {
23985 ms : 'millisecond',
23986 s : 'second',
23987 m : 'minute',
23988 h : 'hour',
23989 d : 'day',
23990 D : 'date',
23991 w : 'week',
23992 W : 'isoWeek',
23993 M : 'month',
23994 y : 'year',
23995 DDD : 'dayOfYear',
23996 e : 'weekday',
23997 E : 'isoWeekday',
23998 gg: 'weekYear',
23999 GG: 'isoWeekYear'
24000 },
24001
24002 camelFunctions = {
24003 dayofyear : 'dayOfYear',
24004 isoweekday : 'isoWeekday',
24005 isoweek : 'isoWeek',
24006 weekyear : 'weekYear',
24007 isoweekyear : 'isoWeekYear'
24008 },
24009
24010 // format function strings
24011 formatFunctions = {},
24012
24013 // tokens to ordinalize and pad
24014 ordinalizeTokens = 'DDD w W M D d'.split(' '),
24015 paddedTokens = 'M D H h m s w W'.split(' '),
24016
24017 formatTokenFunctions = {
24018 M : function () {
24019 return this.month() + 1;
24020 },
24021 MMM : function (format) {
24022 return this.lang().monthsShort(this, format);
24023 },
24024 MMMM : function (format) {
24025 return this.lang().months(this, format);
24026 },
24027 D : function () {
24028 return this.date();
24029 },
24030 DDD : function () {
24031 return this.dayOfYear();
24032 },
24033 d : function () {
24034 return this.day();
24035 },
24036 dd : function (format) {
24037 return this.lang().weekdaysMin(this, format);
24038 },
24039 ddd : function (format) {
24040 return this.lang().weekdaysShort(this, format);
24041 },
24042 dddd : function (format) {
24043 return this.lang().weekdays(this, format);
24044 },
24045 w : function () {
24046 return this.week();
24047 },
24048 W : function () {
24049 return this.isoWeek();
24050 },
24051 YY : function () {
24052 return leftZeroFill(this.year() % 100, 2);
24053 },
24054 YYYY : function () {
24055 return leftZeroFill(this.year(), 4);
24056 },
24057 YYYYY : function () {
24058 return leftZeroFill(this.year(), 5);
24059 },
24060 YYYYYY : function () {
24061 var y = this.year(), sign = y >= 0 ? '+' : '-';
24062 return sign + leftZeroFill(Math.abs(y), 6);
24063 },
24064 gg : function () {
24065 return leftZeroFill(this.weekYear() % 100, 2);
24066 },
24067 gggg : function () {
24068 return leftZeroFill(this.weekYear(), 4);
24069 },
24070 ggggg : function () {
24071 return leftZeroFill(this.weekYear(), 5);
24072 },
24073 GG : function () {
24074 return leftZeroFill(this.isoWeekYear() % 100, 2);
24075 },
24076 GGGG : function () {
24077 return leftZeroFill(this.isoWeekYear(), 4);
24078 },
24079 GGGGG : function () {
24080 return leftZeroFill(this.isoWeekYear(), 5);
24081 },
24082 e : function () {
24083 return this.weekday();
24084 },
24085 E : function () {
24086 return this.isoWeekday();
24087 },
24088 a : function () {
24089 return this.lang().meridiem(this.hours(), this.minutes(), true);
24090 },
24091 A : function () {
24092 return this.lang().meridiem(this.hours(), this.minutes(), false);
24093 },
24094 H : function () {
24095 return this.hours();
24096 },
24097 h : function () {
24098 return this.hours() % 12 || 12;
24099 },
24100 m : function () {
24101 return this.minutes();
24102 },
24103 s : function () {
24104 return this.seconds();
24105 },
24106 S : function () {
24107 return toInt(this.milliseconds() / 100);
24108 },
24109 SS : function () {
24110 return leftZeroFill(toInt(this.milliseconds() / 10), 2);
24111 },
24112 SSS : function () {
24113 return leftZeroFill(this.milliseconds(), 3);
24114 },
24115 SSSS : function () {
24116 return leftZeroFill(this.milliseconds(), 3);
24117 },
24118 Z : function () {
24119 var a = -this.zone(),
24120 b = "+";
24121 if (a < 0) {
24122 a = -a;
24123 b = "-";
24124 }
24125 return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
24126 },
24127 ZZ : function () {
24128 var a = -this.zone(),
24129 b = "+";
24130 if (a < 0) {
24131 a = -a;
24132 b = "-";
24133 }
24134 return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
24135 },
24136 z : function () {
24137 return this.zoneAbbr();
24138 },
24139 zz : function () {
24140 return this.zoneName();
24141 },
24142 X : function () {
24143 return this.unix();
24144 },
24145 Q : function () {
24146 return this.quarter();
24147 }
24148 },
24149
24150 lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
24151
24152 function defaultParsingFlags() {
24153 // We need to deep clone this object, and es5 standard is not very
24154 // helpful.
24155 return {
24156 empty : false,
24157 unusedTokens : [],
24158 unusedInput : [],
24159 overflow : -2,
24160 charsLeftOver : 0,
24161 nullInput : false,
24162 invalidMonth : null,
24163 invalidFormat : false,
24164 userInvalidated : false,
24165 iso: false
24166 };
24167 }
24168
24169 function padToken(func, count) {
24170 return function (a) {
24171 return leftZeroFill(func.call(this, a), count);
24172 };
24173 }
24174 function ordinalizeToken(func, period) {
24175 return function (a) {
24176 return this.lang().ordinal(func.call(this, a), period);
24177 };
24178 }
24179
24180 while (ordinalizeTokens.length) {
24181 i = ordinalizeTokens.pop();
24182 formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
24183 }
24184 while (paddedTokens.length) {
24185 i = paddedTokens.pop();
24186 formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
24187 }
24188 formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
24189
24190
24191 /************************************
24192 Constructors
24193 ************************************/
24194
24195 function Language() {
24196
24197 }
24198
24199 // Moment prototype object
24200 function Moment(config) {
24201 checkOverflow(config);
24202 extend(this, config);
24203 }
24204
24205 // Duration Constructor
24206 function Duration(duration) {
24207 var normalizedInput = normalizeObjectUnits(duration),
24208 years = normalizedInput.year || 0,
24209 months = normalizedInput.month || 0,
24210 weeks = normalizedInput.week || 0,
24211 days = normalizedInput.day || 0,
24212 hours = normalizedInput.hour || 0,
24213 minutes = normalizedInput.minute || 0,
24214 seconds = normalizedInput.second || 0,
24215 milliseconds = normalizedInput.millisecond || 0;
24216
24217 // representation for dateAddRemove
24218 this._milliseconds = +milliseconds +
24219 seconds * 1e3 + // 1000
24220 minutes * 6e4 + // 1000 * 60
24221 hours * 36e5; // 1000 * 60 * 60
24222 // Because of dateAddRemove treats 24 hours as different from a
24223 // day when working around DST, we need to store them separately
24224 this._days = +days +
24225 weeks * 7;
24226 // It is impossible translate months into days without knowing
24227 // which months you are are talking about, so we have to store
24228 // it separately.
24229 this._months = +months +
24230 years * 12;
24231
24232 this._data = {};
24233
24234 this._bubble();
24235 }
24236
24237 /************************************
24238 Helpers
24239 ************************************/
24240
24241
24242 function extend(a, b) {
24243 for (var i in b) {
24244 if (b.hasOwnProperty(i)) {
24245 a[i] = b[i];
24246 }
24247 }
24248
24249 if (b.hasOwnProperty("toString")) {
24250 a.toString = b.toString;
24251 }
24252
24253 if (b.hasOwnProperty("valueOf")) {
24254 a.valueOf = b.valueOf;
24255 }
24256
24257 return a;
24258 }
24259
24260 function cloneMoment(m) {
24261 var result = {}, i;
24262 for (i in m) {
24263 if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
24264 result[i] = m[i];
24265 }
24266 }
24267
24268 return result;
24269 }
24270
24271 function absRound(number) {
24272 if (number < 0) {
24273 return Math.ceil(number);
24274 } else {
24275 return Math.floor(number);
24276 }
24277 }
24278
24279 // left zero fill a number
24280 // see http://jsperf.com/left-zero-filling for performance comparison
24281 function leftZeroFill(number, targetLength, forceSign) {
24282 var output = '' + Math.abs(number),
24283 sign = number >= 0;
24284
24285 while (output.length < targetLength) {
24286 output = '0' + output;
24287 }
24288 return (sign ? (forceSign ? '+' : '') : '-') + output;
24289 }
24290
24291 // helper function for _.addTime and _.subtractTime
24292 function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
24293 var milliseconds = duration._milliseconds,
24294 days = duration._days,
24295 months = duration._months,
24296 minutes,
24297 hours;
24298
24299 if (milliseconds) {
24300 mom._d.setTime(+mom._d + milliseconds * isAdding);
24301 }
24302 // store the minutes and hours so we can restore them
24303 if (days || months) {
24304 minutes = mom.minute();
24305 hours = mom.hour();
24306 }
24307 if (days) {
24308 mom.date(mom.date() + days * isAdding);
24309 }
24310 if (months) {
24311 mom.month(mom.month() + months * isAdding);
24312 }
24313 if (milliseconds && !ignoreUpdateOffset) {
24314 moment.updateOffset(mom);
24315 }
24316 // restore the minutes and hours after possibly changing dst
24317 if (days || months) {
24318 mom.minute(minutes);
24319 mom.hour(hours);
24320 }
24321 }
24322
24323 // check if is an array
24324 function isArray(input) {
24325 return Object.prototype.toString.call(input) === '[object Array]';
24326 }
24327
24328 function isDate(input) {
24329 return Object.prototype.toString.call(input) === '[object Date]' ||
24330 input instanceof Date;
24331 }
24332
24333 // compare two arrays, return the number of differences
24334 function compareArrays(array1, array2, dontConvert) {
24335 var len = Math.min(array1.length, array2.length),
24336 lengthDiff = Math.abs(array1.length - array2.length),
24337 diffs = 0,
24338 i;
24339 for (i = 0; i < len; i++) {
24340 if ((dontConvert && array1[i] !== array2[i]) ||
24341 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
24342 diffs++;
24343 }
24344 }
24345 return diffs + lengthDiff;
24346 }
24347
24348 function normalizeUnits(units) {
24349 if (units) {
24350 var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
24351 units = unitAliases[units] || camelFunctions[lowered] || lowered;
24352 }
24353 return units;
24354 }
24355
24356 function normalizeObjectUnits(inputObject) {
24357 var normalizedInput = {},
24358 normalizedProp,
24359 prop;
24360
24361 for (prop in inputObject) {
24362 if (inputObject.hasOwnProperty(prop)) {
24363 normalizedProp = normalizeUnits(prop);
24364 if (normalizedProp) {
24365 normalizedInput[normalizedProp] = inputObject[prop];
24366 }
24367 }
24368 }
24369
24370 return normalizedInput;
24371 }
24372
24373 function makeList(field) {
24374 var count, setter;
24375
24376 if (field.indexOf('week') === 0) {
24377 count = 7;
24378 setter = 'day';
24379 }
24380 else if (field.indexOf('month') === 0) {
24381 count = 12;
24382 setter = 'month';
24383 }
24384 else {
24385 return;
24386 }
24387
24388 moment[field] = function (format, index) {
24389 var i, getter,
24390 method = moment.fn._lang[field],
24391 results = [];
24392
24393 if (typeof format === 'number') {
24394 index = format;
24395 format = undefined;
24396 }
24397
24398 getter = function (i) {
24399 var m = moment().utc().set(setter, i);
24400 return method.call(moment.fn._lang, m, format || '');
24401 };
24402
24403 if (index != null) {
24404 return getter(index);
24405 }
24406 else {
24407 for (i = 0; i < count; i++) {
24408 results.push(getter(i));
24409 }
24410 return results;
24411 }
24412 };
24413 }
24414
24415 function toInt(argumentForCoercion) {
24416 var coercedNumber = +argumentForCoercion,
24417 value = 0;
24418
24419 if (coercedNumber !== 0 && isFinite(coercedNumber)) {
24420 if (coercedNumber >= 0) {
24421 value = Math.floor(coercedNumber);
24422 } else {
24423 value = Math.ceil(coercedNumber);
24424 }
24425 }
24426
24427 return value;
24428 }
24429
24430 function daysInMonth(year, month) {
24431 return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
24432 }
24433
24434 function daysInYear(year) {
24435 return isLeapYear(year) ? 366 : 365;
24436 }
24437
24438 function isLeapYear(year) {
24439 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
24440 }
24441
24442 function checkOverflow(m) {
24443 var overflow;
24444 if (m._a && m._pf.overflow === -2) {
24445 overflow =
24446 m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
24447 m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
24448 m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
24449 m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
24450 m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
24451 m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
24452 -1;
24453
24454 if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
24455 overflow = DATE;
24456 }
24457
24458 m._pf.overflow = overflow;
24459 }
24460 }
24461
24462 function isValid(m) {
24463 if (m._isValid == null) {
24464 m._isValid = !isNaN(m._d.getTime()) &&
24465 m._pf.overflow < 0 &&
24466 !m._pf.empty &&
24467 !m._pf.invalidMonth &&
24468 !m._pf.nullInput &&
24469 !m._pf.invalidFormat &&
24470 !m._pf.userInvalidated;
24471
24472 if (m._strict) {
24473 m._isValid = m._isValid &&
24474 m._pf.charsLeftOver === 0 &&
24475 m._pf.unusedTokens.length === 0;
24476 }
24477 }
24478 return m._isValid;
24479 }
24480
24481 function normalizeLanguage(key) {
24482 return key ? key.toLowerCase().replace('_', '-') : key;
24483 }
24484
24485 // Return a moment from input, that is local/utc/zone equivalent to model.
24486 function makeAs(input, model) {
24487 return model._isUTC ? moment(input).zone(model._offset || 0) :
24488 moment(input).local();
24489 }
24490
24491 /************************************
24492 Languages
24493 ************************************/
24494
24495
24496 extend(Language.prototype, {
24497
24498 set : function (config) {
24499 var prop, i;
24500 for (i in config) {
24501 prop = config[i];
24502 if (typeof prop === 'function') {
24503 this[i] = prop;
24504 } else {
24505 this['_' + i] = prop;
24506 }
24507 }
24508 },
24509
24510 _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
24511 months : function (m) {
24512 return this._months[m.month()];
24513 },
24514
24515 _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
24516 monthsShort : function (m) {
24517 return this._monthsShort[m.month()];
24518 },
24519
24520 monthsParse : function (monthName) {
24521 var i, mom, regex;
24522
24523 if (!this._monthsParse) {
24524 this._monthsParse = [];
24525 }
24526
24527 for (i = 0; i < 12; i++) {
24528 // make the regex if we don't have it already
24529 if (!this._monthsParse[i]) {
24530 mom = moment.utc([2000, i]);
24531 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
24532 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
24533 }
24534 // test the regex
24535 if (this._monthsParse[i].test(monthName)) {
24536 return i;
24537 }
24538 }
24539 },
24540
24541 _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
24542 weekdays : function (m) {
24543 return this._weekdays[m.day()];
24544 },
24545
24546 _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
24547 weekdaysShort : function (m) {
24548 return this._weekdaysShort[m.day()];
24549 },
24550
24551 _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
24552 weekdaysMin : function (m) {
24553 return this._weekdaysMin[m.day()];
24554 },
24555
24556 weekdaysParse : function (weekdayName) {
24557 var i, mom, regex;
24558
24559 if (!this._weekdaysParse) {
24560 this._weekdaysParse = [];
24561 }
24562
24563 for (i = 0; i < 7; i++) {
24564 // make the regex if we don't have it already
24565 if (!this._weekdaysParse[i]) {
24566 mom = moment([2000, 1]).day(i);
24567 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
24568 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
24569 }
24570 // test the regex
24571 if (this._weekdaysParse[i].test(weekdayName)) {
24572 return i;
24573 }
24574 }
24575 },
24576
24577 _longDateFormat : {
24578 LT : "h:mm A",
24579 L : "MM/DD/YYYY",
24580 LL : "MMMM D YYYY",
24581 LLL : "MMMM D YYYY LT",
24582 LLLL : "dddd, MMMM D YYYY LT"
24583 },
24584 longDateFormat : function (key) {
24585 var output = this._longDateFormat[key];
24586 if (!output && this._longDateFormat[key.toUpperCase()]) {
24587 output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
24588 return val.slice(1);
24589 });
24590 this._longDateFormat[key] = output;
24591 }
24592 return output;
24593 },
24594
24595 isPM : function (input) {
24596 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
24597 // Using charAt should be more compatible.
24598 return ((input + '').toLowerCase().charAt(0) === 'p');
24599 },
24600
24601 _meridiemParse : /[ap]\.?m?\.?/i,
24602 meridiem : function (hours, minutes, isLower) {
24603 if (hours > 11) {
24604 return isLower ? 'pm' : 'PM';
24605 } else {
24606 return isLower ? 'am' : 'AM';
24607 }
24608 },
24609
24610 _calendar : {
24611 sameDay : '[Today at] LT',
24612 nextDay : '[Tomorrow at] LT',
24613 nextWeek : 'dddd [at] LT',
24614 lastDay : '[Yesterday at] LT',
24615 lastWeek : '[Last] dddd [at] LT',
24616 sameElse : 'L'
24617 },
24618 calendar : function (key, mom) {
24619 var output = this._calendar[key];
24620 return typeof output === 'function' ? output.apply(mom) : output;
24621 },
24622
24623 _relativeTime : {
24624 future : "in %s",
24625 past : "%s ago",
24626 s : "a few seconds",
24627 m : "a minute",
24628 mm : "%d minutes",
24629 h : "an hour",
24630 hh : "%d hours",
24631 d : "a day",
24632 dd : "%d days",
24633 M : "a month",
24634 MM : "%d months",
24635 y : "a year",
24636 yy : "%d years"
24637 },
24638 relativeTime : function (number, withoutSuffix, string, isFuture) {
24639 var output = this._relativeTime[string];
24640 return (typeof output === 'function') ?
24641 output(number, withoutSuffix, string, isFuture) :
24642 output.replace(/%d/i, number);
24643 },
24644 pastFuture : function (diff, output) {
24645 var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
24646 return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
24647 },
24648
24649 ordinal : function (number) {
24650 return this._ordinal.replace("%d", number);
24651 },
24652 _ordinal : "%d",
24653
24654 preparse : function (string) {
24655 return string;
24656 },
24657
24658 postformat : function (string) {
24659 return string;
24660 },
24661
24662 week : function (mom) {
24663 return weekOfYear(mom, this._week.dow, this._week.doy).week;
24664 },
24665
24666 _week : {
24667 dow : 0, // Sunday is the first day of the week.
24668 doy : 6 // The week that contains Jan 1st is the first week of the year.
24669 },
24670
24671 _invalidDate: 'Invalid date',
24672 invalidDate: function () {
24673 return this._invalidDate;
24674 }
24675 });
24676
24677 // Loads a language definition into the `languages` cache. The function
24678 // takes a key and optionally values. If not in the browser and no values
24679 // are provided, it will load the language file module. As a convenience,
24680 // this function also returns the language values.
24681 function loadLang(key, values) {
24682 values.abbr = key;
24683 if (!languages[key]) {
24684 languages[key] = new Language();
24685 }
24686 languages[key].set(values);
24687 return languages[key];
24688 }
24689
24690 // Remove a language from the `languages` cache. Mostly useful in tests.
24691 function unloadLang(key) {
24692 delete languages[key];
24693 }
24694
24695 // Determines which language definition to use and returns it.
24696 //
24697 // With no parameters, it will return the global language. If you
24698 // pass in a language key, such as 'en', it will return the
24699 // definition for 'en', so long as 'en' has already been loaded using
24700 // moment.lang.
24701 function getLangDefinition(key) {
24702 var i = 0, j, lang, next, split,
24703 get = function (k) {
24704 if (!languages[k] && hasModule) {
24705 try {
24706 require('./lang/' + k);
24707 } catch (e) { }
24708 }
24709 return languages[k];
24710 };
24711
24712 if (!key) {
24713 return moment.fn._lang;
24714 }
24715
24716 if (!isArray(key)) {
24717 //short-circuit everything else
24718 lang = get(key);
24719 if (lang) {
24720 return lang;
24721 }
24722 key = [key];
24723 }
24724
24725 //pick the language from the array
24726 //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
24727 //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
24728 while (i < key.length) {
24729 split = normalizeLanguage(key[i]).split('-');
24730 j = split.length;
24731 next = normalizeLanguage(key[i + 1]);
24732 next = next ? next.split('-') : null;
24733 while (j > 0) {
24734 lang = get(split.slice(0, j).join('-'));
24735 if (lang) {
24736 return lang;
24737 }
24738 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
24739 //the next array item is better than a shallower substring of this one
24740 break;
24741 }
24742 j--;
24743 }
24744 i++;
24745 }
24746 return moment.fn._lang;
24747 }
24748
24749 /************************************
24750 Formatting
24751 ************************************/
24752
24753
24754 function removeFormattingTokens(input) {
24755 if (input.match(/\[[\s\S]/)) {
24756 return input.replace(/^\[|\]$/g, "");
24757 }
24758 return input.replace(/\\/g, "");
24759 }
24760
24761 function makeFormatFunction(format) {
24762 var array = format.match(formattingTokens), i, length;
24763
24764 for (i = 0, length = array.length; i < length; i++) {
24765 if (formatTokenFunctions[array[i]]) {
24766 array[i] = formatTokenFunctions[array[i]];
24767 } else {
24768 array[i] = removeFormattingTokens(array[i]);
24769 }
24770 }
24771
24772 return function (mom) {
24773 var output = "";
24774 for (i = 0; i < length; i++) {
24775 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
24776 }
24777 return output;
24778 };
24779 }
24780
24781 // format date using native date object
24782 function formatMoment(m, format) {
24783
24784 if (!m.isValid()) {
24785 return m.lang().invalidDate();
24786 }
24787
24788 format = expandFormat(format, m.lang());
24789
24790 if (!formatFunctions[format]) {
24791 formatFunctions[format] = makeFormatFunction(format);
24792 }
24793
24794 return formatFunctions[format](m);
24795 }
24796
24797 function expandFormat(format, lang) {
24798 var i = 5;
24799
24800 function replaceLongDateFormatTokens(input) {
24801 return lang.longDateFormat(input) || input;
24802 }
24803
24804 localFormattingTokens.lastIndex = 0;
24805 while (i >= 0 && localFormattingTokens.test(format)) {
24806 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
24807 localFormattingTokens.lastIndex = 0;
24808 i -= 1;
24809 }
24810
24811 return format;
24812 }
24813
24814
24815 /************************************
24816 Parsing
24817 ************************************/
24818
24819
24820 // get the regex to find the next token
24821 function getParseRegexForToken(token, config) {
24822 var a, strict = config._strict;
24823 switch (token) {
24824 case 'DDDD':
24825 return parseTokenThreeDigits;
24826 case 'YYYY':
24827 case 'GGGG':
24828 case 'gggg':
24829 return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
24830 case 'Y':
24831 case 'G':
24832 case 'g':
24833 return parseTokenSignedNumber;
24834 case 'YYYYYY':
24835 case 'YYYYY':
24836 case 'GGGGG':
24837 case 'ggggg':
24838 return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
24839 case 'S':
24840 if (strict) { return parseTokenOneDigit; }
24841 /* falls through */
24842 case 'SS':
24843 if (strict) { return parseTokenTwoDigits; }
24844 /* falls through */
24845 case 'SSS':
24846 if (strict) { return parseTokenThreeDigits; }
24847 /* falls through */
24848 case 'DDD':
24849 return parseTokenOneToThreeDigits;
24850 case 'MMM':
24851 case 'MMMM':
24852 case 'dd':
24853 case 'ddd':
24854 case 'dddd':
24855 return parseTokenWord;
24856 case 'a':
24857 case 'A':
24858 return getLangDefinition(config._l)._meridiemParse;
24859 case 'X':
24860 return parseTokenTimestampMs;
24861 case 'Z':
24862 case 'ZZ':
24863 return parseTokenTimezone;
24864 case 'T':
24865 return parseTokenT;
24866 case 'SSSS':
24867 return parseTokenDigits;
24868 case 'MM':
24869 case 'DD':
24870 case 'YY':
24871 case 'GG':
24872 case 'gg':
24873 case 'HH':
24874 case 'hh':
24875 case 'mm':
24876 case 'ss':
24877 case 'ww':
24878 case 'WW':
24879 return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
24880 case 'M':
24881 case 'D':
24882 case 'd':
24883 case 'H':
24884 case 'h':
24885 case 'm':
24886 case 's':
24887 case 'w':
24888 case 'W':
24889 case 'e':
24890 case 'E':
24891 return parseTokenOneOrTwoDigits;
24892 default :
24893 a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
24894 return a;
24895 }
24896 }
24897
24898 function timezoneMinutesFromString(string) {
24899 string = string || "";
24900 var possibleTzMatches = (string.match(parseTokenTimezone) || []),
24901 tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
24902 parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
24903 minutes = +(parts[1] * 60) + toInt(parts[2]);
24904
24905 return parts[0] === '+' ? -minutes : minutes;
24906 }
24907
24908 // function to convert string input to date
24909 function addTimeToArrayFromToken(token, input, config) {
24910 var a, datePartArray = config._a;
24911
24912 switch (token) {
24913 // MONTH
24914 case 'M' : // fall through to MM
24915 case 'MM' :
24916 if (input != null) {
24917 datePartArray[MONTH] = toInt(input) - 1;
24918 }
24919 break;
24920 case 'MMM' : // fall through to MMMM
24921 case 'MMMM' :
24922 a = getLangDefinition(config._l).monthsParse(input);
24923 // if we didn't find a month name, mark the date as invalid.
24924 if (a != null) {
24925 datePartArray[MONTH] = a;
24926 } else {
24927 config._pf.invalidMonth = input;
24928 }
24929 break;
24930 // DAY OF MONTH
24931 case 'D' : // fall through to DD
24932 case 'DD' :
24933 if (input != null) {
24934 datePartArray[DATE] = toInt(input);
24935 }
24936 break;
24937 // DAY OF YEAR
24938 case 'DDD' : // fall through to DDDD
24939 case 'DDDD' :
24940 if (input != null) {
24941 config._dayOfYear = toInt(input);
24942 }
24943
24944 break;
24945 // YEAR
24946 case 'YY' :
24947 datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
24948 break;
24949 case 'YYYY' :
24950 case 'YYYYY' :
24951 case 'YYYYYY' :
24952 datePartArray[YEAR] = toInt(input);
24953 break;
24954 // AM / PM
24955 case 'a' : // fall through to A
24956 case 'A' :
24957 config._isPm = getLangDefinition(config._l).isPM(input);
24958 break;
24959 // 24 HOUR
24960 case 'H' : // fall through to hh
24961 case 'HH' : // fall through to hh
24962 case 'h' : // fall through to hh
24963 case 'hh' :
24964 datePartArray[HOUR] = toInt(input);
24965 break;
24966 // MINUTE
24967 case 'm' : // fall through to mm
24968 case 'mm' :
24969 datePartArray[MINUTE] = toInt(input);
24970 break;
24971 // SECOND
24972 case 's' : // fall through to ss
24973 case 'ss' :
24974 datePartArray[SECOND] = toInt(input);
24975 break;
24976 // MILLISECOND
24977 case 'S' :
24978 case 'SS' :
24979 case 'SSS' :
24980 case 'SSSS' :
24981 datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
24982 break;
24983 // UNIX TIMESTAMP WITH MS
24984 case 'X':
24985 config._d = new Date(parseFloat(input) * 1000);
24986 break;
24987 // TIMEZONE
24988 case 'Z' : // fall through to ZZ
24989 case 'ZZ' :
24990 config._useUTC = true;
24991 config._tzm = timezoneMinutesFromString(input);
24992 break;
24993 case 'w':
24994 case 'ww':
24995 case 'W':
24996 case 'WW':
24997 case 'd':
24998 case 'dd':
24999 case 'ddd':
25000 case 'dddd':
25001 case 'e':
25002 case 'E':
25003 token = token.substr(0, 1);
25004 /* falls through */
25005 case 'gg':
25006 case 'gggg':
25007 case 'GG':
25008 case 'GGGG':
25009 case 'GGGGG':
25010 token = token.substr(0, 2);
25011 if (input) {
25012 config._w = config._w || {};
25013 config._w[token] = input;
25014 }
25015 break;
25016 }
25017 }
25018
25019 // convert an array to a date.
25020 // the array should mirror the parameters below
25021 // note: all values past the year are optional and will default to the lowest possible value.
25022 // [year, month, day , hour, minute, second, millisecond]
25023 function dateFromConfig(config) {
25024 var i, date, input = [], currentDate,
25025 yearToUse, fixYear, w, temp, lang, weekday, week;
25026
25027 if (config._d) {
25028 return;
25029 }
25030
25031 currentDate = currentDateArray(config);
25032
25033 //compute day of the year from weeks and weekdays
25034 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
25035 fixYear = function (val) {
25036 var int_val = parseInt(val, 10);
25037 return val ?
25038 (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
25039 (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
25040 };
25041
25042 w = config._w;
25043 if (w.GG != null || w.W != null || w.E != null) {
25044 temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
25045 }
25046 else {
25047 lang = getLangDefinition(config._l);
25048 weekday = w.d != null ? parseWeekday(w.d, lang) :
25049 (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0);
25050
25051 week = parseInt(w.w, 10) || 1;
25052
25053 //if we're parsing 'd', then the low day numbers may be next week
25054 if (w.d != null && weekday < lang._week.dow) {
25055 week++;
25056 }
25057
25058 temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
25059 }
25060
25061 config._a[YEAR] = temp.year;
25062 config._dayOfYear = temp.dayOfYear;
25063 }
25064
25065 //if the day of the year is set, figure out what it is
25066 if (config._dayOfYear) {
25067 yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
25068
25069 if (config._dayOfYear > daysInYear(yearToUse)) {
25070 config._pf._overflowDayOfYear = true;
25071 }
25072
25073 date = makeUTCDate(yearToUse, 0, config._dayOfYear);
25074 config._a[MONTH] = date.getUTCMonth();
25075 config._a[DATE] = date.getUTCDate();
25076 }
25077
25078 // Default to current date.
25079 // * if no year, month, day of month are given, default to today
25080 // * if day of month is given, default month and year
25081 // * if month is given, default only year
25082 // * if year is given, don't default anything
25083 for (i = 0; i < 3 && config._a[i] == null; ++i) {
25084 config._a[i] = input[i] = currentDate[i];
25085 }
25086
25087 // Zero out whatever was not defaulted, including time
25088 for (; i < 7; i++) {
25089 config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
25090 }
25091
25092 // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
25093 input[HOUR] += toInt((config._tzm || 0) / 60);
25094 input[MINUTE] += toInt((config._tzm || 0) % 60);
25095
25096 config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
25097 }
25098
25099 function dateFromObject(config) {
25100 var normalizedInput;
25101
25102 if (config._d) {
25103 return;
25104 }
25105
25106 normalizedInput = normalizeObjectUnits(config._i);
25107 config._a = [
25108 normalizedInput.year,
25109 normalizedInput.month,
25110 normalizedInput.day,
25111 normalizedInput.hour,
25112 normalizedInput.minute,
25113 normalizedInput.second,
25114 normalizedInput.millisecond
25115 ];
25116
25117 dateFromConfig(config);
25118 }
25119
25120 function currentDateArray(config) {
25121 var now = new Date();
25122 if (config._useUTC) {
25123 return [
25124 now.getUTCFullYear(),
25125 now.getUTCMonth(),
25126 now.getUTCDate()
25127 ];
25128 } else {
25129 return [now.getFullYear(), now.getMonth(), now.getDate()];
25130 }
25131 }
25132
25133 // date from string and format string
25134 function makeDateFromStringAndFormat(config) {
25135
25136 config._a = [];
25137 config._pf.empty = true;
25138
25139 // This array is used to make a Date, either with `new Date` or `Date.UTC`
25140 var lang = getLangDefinition(config._l),
25141 string = '' + config._i,
25142 i, parsedInput, tokens, token, skipped,
25143 stringLength = string.length,
25144 totalParsedInputLength = 0;
25145
25146 tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
25147
25148 for (i = 0; i < tokens.length; i++) {
25149 token = tokens[i];
25150 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
25151 if (parsedInput) {
25152 skipped = string.substr(0, string.indexOf(parsedInput));
25153 if (skipped.length > 0) {
25154 config._pf.unusedInput.push(skipped);
25155 }
25156 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
25157 totalParsedInputLength += parsedInput.length;
25158 }
25159 // don't parse if it's not a known token
25160 if (formatTokenFunctions[token]) {
25161 if (parsedInput) {
25162 config._pf.empty = false;
25163 }
25164 else {
25165 config._pf.unusedTokens.push(token);
25166 }
25167 addTimeToArrayFromToken(token, parsedInput, config);
25168 }
25169 else if (config._strict && !parsedInput) {
25170 config._pf.unusedTokens.push(token);
25171 }
25172 }
25173
25174 // add remaining unparsed input length to the string
25175 config._pf.charsLeftOver = stringLength - totalParsedInputLength;
25176 if (string.length > 0) {
25177 config._pf.unusedInput.push(string);
25178 }
25179
25180 // handle am pm
25181 if (config._isPm && config._a[HOUR] < 12) {
25182 config._a[HOUR] += 12;
25183 }
25184 // if is 12 am, change hours to 0
25185 if (config._isPm === false && config._a[HOUR] === 12) {
25186 config._a[HOUR] = 0;
25187 }
25188
25189 dateFromConfig(config);
25190 checkOverflow(config);
25191 }
25192
25193 function unescapeFormat(s) {
25194 return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
25195 return p1 || p2 || p3 || p4;
25196 });
25197 }
25198
25199 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
25200 function regexpEscape(s) {
25201 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
25202 }
25203
25204 // date from string and array of format strings
25205 function makeDateFromStringAndArray(config) {
25206 var tempConfig,
25207 bestMoment,
25208
25209 scoreToBeat,
25210 i,
25211 currentScore;
25212
25213 if (config._f.length === 0) {
25214 config._pf.invalidFormat = true;
25215 config._d = new Date(NaN);
25216 return;
25217 }
25218
25219 for (i = 0; i < config._f.length; i++) {
25220 currentScore = 0;
25221 tempConfig = extend({}, config);
25222 tempConfig._pf = defaultParsingFlags();
25223 tempConfig._f = config._f[i];
25224 makeDateFromStringAndFormat(tempConfig);
25225
25226 if (!isValid(tempConfig)) {
25227 continue;
25228 }
25229
25230 // if there is any input that was not parsed add a penalty for that format
25231 currentScore += tempConfig._pf.charsLeftOver;
25232
25233 //or tokens
25234 currentScore += tempConfig._pf.unusedTokens.length * 10;
25235
25236 tempConfig._pf.score = currentScore;
25237
25238 if (scoreToBeat == null || currentScore < scoreToBeat) {
25239 scoreToBeat = currentScore;
25240 bestMoment = tempConfig;
25241 }
25242 }
25243
25244 extend(config, bestMoment || tempConfig);
25245 }
25246
25247 // date from iso format
25248 function makeDateFromString(config) {
25249 var i, l,
25250 string = config._i,
25251 match = isoRegex.exec(string);
25252
25253 if (match) {
25254 config._pf.iso = true;
25255 for (i = 0, l = isoDates.length; i < l; i++) {
25256 if (isoDates[i][1].exec(string)) {
25257 // match[5] should be "T" or undefined
25258 config._f = isoDates[i][0] + (match[6] || " ");
25259 break;
25260 }
25261 }
25262 for (i = 0, l = isoTimes.length; i < l; i++) {
25263 if (isoTimes[i][1].exec(string)) {
25264 config._f += isoTimes[i][0];
25265 break;
25266 }
25267 }
25268 if (string.match(parseTokenTimezone)) {
25269 config._f += "Z";
25270 }
25271 makeDateFromStringAndFormat(config);
25272 }
25273 else {
25274 config._d = new Date(string);
25275 }
25276 }
25277
25278 function makeDateFromInput(config) {
25279 var input = config._i,
25280 matched = aspNetJsonRegex.exec(input);
25281
25282 if (input === undefined) {
25283 config._d = new Date();
25284 } else if (matched) {
25285 config._d = new Date(+matched[1]);
25286 } else if (typeof input === 'string') {
25287 makeDateFromString(config);
25288 } else if (isArray(input)) {
25289 config._a = input.slice(0);
25290 dateFromConfig(config);
25291 } else if (isDate(input)) {
25292 config._d = new Date(+input);
25293 } else if (typeof(input) === 'object') {
25294 dateFromObject(config);
25295 } else {
25296 config._d = new Date(input);
25297 }
25298 }
25299
25300 function makeDate(y, m, d, h, M, s, ms) {
25301 //can't just apply() to create a date:
25302 //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
25303 var date = new Date(y, m, d, h, M, s, ms);
25304
25305 //the date constructor doesn't accept years < 1970
25306 if (y < 1970) {
25307 date.setFullYear(y);
25308 }
25309 return date;
25310 }
25311
25312 function makeUTCDate(y) {
25313 var date = new Date(Date.UTC.apply(null, arguments));
25314 if (y < 1970) {
25315 date.setUTCFullYear(y);
25316 }
25317 return date;
25318 }
25319
25320 function parseWeekday(input, language) {
25321 if (typeof input === 'string') {
25322 if (!isNaN(input)) {
25323 input = parseInt(input, 10);
25324 }
25325 else {
25326 input = language.weekdaysParse(input);
25327 if (typeof input !== 'number') {
25328 return null;
25329 }
25330 }
25331 }
25332 return input;
25333 }
25334
25335 /************************************
25336 Relative Time
25337 ************************************/
25338
25339
25340 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
25341 function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
25342 return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
25343 }
25344
25345 function relativeTime(milliseconds, withoutSuffix, lang) {
25346 var seconds = round(Math.abs(milliseconds) / 1000),
25347 minutes = round(seconds / 60),
25348 hours = round(minutes / 60),
25349 days = round(hours / 24),
25350 years = round(days / 365),
25351 args = seconds < 45 && ['s', seconds] ||
25352 minutes === 1 && ['m'] ||
25353 minutes < 45 && ['mm', minutes] ||
25354 hours === 1 && ['h'] ||
25355 hours < 22 && ['hh', hours] ||
25356 days === 1 && ['d'] ||
25357 days <= 25 && ['dd', days] ||
25358 days <= 45 && ['M'] ||
25359 days < 345 && ['MM', round(days / 30)] ||
25360 years === 1 && ['y'] || ['yy', years];
25361 args[2] = withoutSuffix;
25362 args[3] = milliseconds > 0;
25363 args[4] = lang;
25364 return substituteTimeAgo.apply({}, args);
25365 }
25366
25367
25368 /************************************
25369 Week of Year
25370 ************************************/
25371
25372
25373 // firstDayOfWeek 0 = sun, 6 = sat
25374 // the day of the week that starts the week
25375 // (usually sunday or monday)
25376 // firstDayOfWeekOfYear 0 = sun, 6 = sat
25377 // the first week is the week that contains the first
25378 // of this day of the week
25379 // (eg. ISO weeks use thursday (4))
25380 function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
25381 var end = firstDayOfWeekOfYear - firstDayOfWeek,
25382 daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
25383 adjustedMoment;
25384
25385
25386 if (daysToDayOfWeek > end) {
25387 daysToDayOfWeek -= 7;
25388 }
25389
25390 if (daysToDayOfWeek < end - 7) {
25391 daysToDayOfWeek += 7;
25392 }
25393
25394 adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
25395 return {
25396 week: Math.ceil(adjustedMoment.dayOfYear() / 7),
25397 year: adjustedMoment.year()
25398 };
25399 }
25400
25401 //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
25402 function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
25403 var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
25404
25405 weekday = weekday != null ? weekday : firstDayOfWeek;
25406 daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
25407 dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
25408
25409 return {
25410 year: dayOfYear > 0 ? year : year - 1,
25411 dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
25412 };
25413 }
25414
25415 /************************************
25416 Top Level Functions
25417 ************************************/
25418
25419 function makeMoment(config) {
25420 var input = config._i,
25421 format = config._f;
25422
25423 if (input === null) {
25424 return moment.invalid({nullInput: true});
25425 }
25426
25427 if (typeof input === 'string') {
25428 config._i = input = getLangDefinition().preparse(input);
25429 }
25430
25431 if (moment.isMoment(input)) {
25432 config = cloneMoment(input);
25433
25434 config._d = new Date(+input._d);
25435 } else if (format) {
25436 if (isArray(format)) {
25437 makeDateFromStringAndArray(config);
25438 } else {
25439 makeDateFromStringAndFormat(config);
25440 }
25441 } else {
25442 makeDateFromInput(config);
25443 }
25444
25445 return new Moment(config);
25446 }
25447
25448 moment = function (input, format, lang, strict) {
25449 var c;
25450
25451 if (typeof(lang) === "boolean") {
25452 strict = lang;
25453 lang = undefined;
25454 }
25455 // object construction must be done this way.
25456 // https://github.com/moment/moment/issues/1423
25457 c = {};
25458 c._isAMomentObject = true;
25459 c._i = input;
25460 c._f = format;
25461 c._l = lang;
25462 c._strict = strict;
25463 c._isUTC = false;
25464 c._pf = defaultParsingFlags();
25465
25466 return makeMoment(c);
25467 };
25468
25469 // creating with utc
25470 moment.utc = function (input, format, lang, strict) {
25471 var c;
25472
25473 if (typeof(lang) === "boolean") {
25474 strict = lang;
25475 lang = undefined;
25476 }
25477 // object construction must be done this way.
25478 // https://github.com/moment/moment/issues/1423
25479 c = {};
25480 c._isAMomentObject = true;
25481 c._useUTC = true;
25482 c._isUTC = true;
25483 c._l = lang;
25484 c._i = input;
25485 c._f = format;
25486 c._strict = strict;
25487 c._pf = defaultParsingFlags();
25488
25489 return makeMoment(c).utc();
25490 };
25491
25492 // creating with unix timestamp (in seconds)
25493 moment.unix = function (input) {
25494 return moment(input * 1000);
25495 };
25496
25497 // duration
25498 moment.duration = function (input, key) {
25499 var duration = input,
25500 // matching against regexp is expensive, do it on demand
25501 match = null,
25502 sign,
25503 ret,
25504 parseIso;
25505
25506 if (moment.isDuration(input)) {
25507 duration = {
25508 ms: input._milliseconds,
25509 d: input._days,
25510 M: input._months
25511 };
25512 } else if (typeof input === 'number') {
25513 duration = {};
25514 if (key) {
25515 duration[key] = input;
25516 } else {
25517 duration.milliseconds = input;
25518 }
25519 } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
25520 sign = (match[1] === "-") ? -1 : 1;
25521 duration = {
25522 y: 0,
25523 d: toInt(match[DATE]) * sign,
25524 h: toInt(match[HOUR]) * sign,
25525 m: toInt(match[MINUTE]) * sign,
25526 s: toInt(match[SECOND]) * sign,
25527 ms: toInt(match[MILLISECOND]) * sign
25528 };
25529 } else if (!!(match = isoDurationRegex.exec(input))) {
25530 sign = (match[1] === "-") ? -1 : 1;
25531 parseIso = function (inp) {
25532 // We'd normally use ~~inp for this, but unfortunately it also
25533 // converts floats to ints.
25534 // inp may be undefined, so careful calling replace on it.
25535 var res = inp && parseFloat(inp.replace(',', '.'));
25536 // apply sign while we're at it
25537 return (isNaN(res) ? 0 : res) * sign;
25538 };
25539 duration = {
25540 y: parseIso(match[2]),
25541 M: parseIso(match[3]),
25542 d: parseIso(match[4]),
25543 h: parseIso(match[5]),
25544 m: parseIso(match[6]),
25545 s: parseIso(match[7]),
25546 w: parseIso(match[8])
25547 };
25548 }
25549
25550 ret = new Duration(duration);
25551
25552 if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
25553 ret._lang = input._lang;
25554 }
25555
25556 return ret;
25557 };
25558
25559 // version number
25560 moment.version = VERSION;
25561
25562 // default format
25563 moment.defaultFormat = isoFormat;
25564
25565 // This function will be called whenever a moment is mutated.
25566 // It is intended to keep the offset in sync with the timezone.
25567 moment.updateOffset = function () {};
25568
25569 // This function will load languages and then set the global language. If
25570 // no arguments are passed in, it will simply return the current global
25571 // language key.
25572 moment.lang = function (key, values) {
25573 var r;
25574 if (!key) {
25575 return moment.fn._lang._abbr;
25576 }
25577 if (values) {
25578 loadLang(normalizeLanguage(key), values);
25579 } else if (values === null) {
25580 unloadLang(key);
25581 key = 'en';
25582 } else if (!languages[key]) {
25583 getLangDefinition(key);
25584 }
25585 r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
25586 return r._abbr;
25587 };
25588
25589 // returns language data
25590 moment.langData = function (key) {
25591 if (key && key._lang && key._lang._abbr) {
25592 key = key._lang._abbr;
25593 }
25594 return getLangDefinition(key);
25595 };
25596
25597 // compare moment object
25598 moment.isMoment = function (obj) {
25599 return obj instanceof Moment ||
25600 (obj != null && obj.hasOwnProperty('_isAMomentObject'));
25601 };
25602
25603 // for typechecking Duration objects
25604 moment.isDuration = function (obj) {
25605 return obj instanceof Duration;
25606 };
25607
25608 for (i = lists.length - 1; i >= 0; --i) {
25609 makeList(lists[i]);
25610 }
25611
25612 moment.normalizeUnits = function (units) {
25613 return normalizeUnits(units);
25614 };
25615
25616 moment.invalid = function (flags) {
25617 var m = moment.utc(NaN);
25618 if (flags != null) {
25619 extend(m._pf, flags);
25620 }
25621 else {
25622 m._pf.userInvalidated = true;
25623 }
25624
25625 return m;
25626 };
25627
25628 moment.parseZone = function (input) {
25629 return moment(input).parseZone();
25630 };
25631
25632 /************************************
25633 Moment Prototype
25634 ************************************/
25635
25636
25637 extend(moment.fn = Moment.prototype, {
25638
25639 clone : function () {
25640 return moment(this);
25641 },
25642
25643 valueOf : function () {
25644 return +this._d + ((this._offset || 0) * 60000);
25645 },
25646
25647 unix : function () {
25648 return Math.floor(+this / 1000);
25649 },
25650
25651 toString : function () {
25652 return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
25653 },
25654
25655 toDate : function () {
25656 return this._offset ? new Date(+this) : this._d;
25657 },
25658
25659 toISOString : function () {
25660 var m = moment(this).utc();
25661 if (0 < m.year() && m.year() <= 9999) {
25662 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
25663 } else {
25664 return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
25665 }
25666 },
25667
25668 toArray : function () {
25669 var m = this;
25670 return [
25671 m.year(),
25672 m.month(),
25673 m.date(),
25674 m.hours(),
25675 m.minutes(),
25676 m.seconds(),
25677 m.milliseconds()
25678 ];
25679 },
25680
25681 isValid : function () {
25682 return isValid(this);
25683 },
25684
25685 isDSTShifted : function () {
25686
25687 if (this._a) {
25688 return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
25689 }
25690
25691 return false;
25692 },
25693
25694 parsingFlags : function () {
25695 return extend({}, this._pf);
25696 },
25697
25698 invalidAt: function () {
25699 return this._pf.overflow;
25700 },
25701
25702 utc : function () {
25703 return this.zone(0);
25704 },
25705
25706 local : function () {
25707 this.zone(0);
25708 this._isUTC = false;
25709 return this;
25710 },
25711
25712 format : function (inputString) {
25713 var output = formatMoment(this, inputString || moment.defaultFormat);
25714 return this.lang().postformat(output);
25715 },
25716
25717 add : function (input, val) {
25718 var dur;
25719 // switch args to support add('s', 1) and add(1, 's')
25720 if (typeof input === 'string') {
25721 dur = moment.duration(+val, input);
25722 } else {
25723 dur = moment.duration(input, val);
25724 }
25725 addOrSubtractDurationFromMoment(this, dur, 1);
25726 return this;
25727 },
25728
25729 subtract : function (input, val) {
25730 var dur;
25731 // switch args to support subtract('s', 1) and subtract(1, 's')
25732 if (typeof input === 'string') {
25733 dur = moment.duration(+val, input);
25734 } else {
25735 dur = moment.duration(input, val);
25736 }
25737 addOrSubtractDurationFromMoment(this, dur, -1);
25738 return this;
25739 },
25740
25741 diff : function (input, units, asFloat) {
25742 var that = makeAs(input, this),
25743 zoneDiff = (this.zone() - that.zone()) * 6e4,
25744 diff, output;
25745
25746 units = normalizeUnits(units);
25747
25748 if (units === 'year' || units === 'month') {
25749 // average number of days in the months in the given dates
25750 diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
25751 // difference in months
25752 output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
25753 // adjust by taking difference in days, average number of days
25754 // and dst in the given months.
25755 output += ((this - moment(this).startOf('month')) -
25756 (that - moment(that).startOf('month'))) / diff;
25757 // same as above but with zones, to negate all dst
25758 output -= ((this.zone() - moment(this).startOf('month').zone()) -
25759 (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
25760 if (units === 'year') {
25761 output = output / 12;
25762 }
25763 } else {
25764 diff = (this - that);
25765 output = units === 'second' ? diff / 1e3 : // 1000
25766 units === 'minute' ? diff / 6e4 : // 1000 * 60
25767 units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
25768 units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
25769 units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
25770 diff;
25771 }
25772 return asFloat ? output : absRound(output);
25773 },
25774
25775 from : function (time, withoutSuffix) {
25776 return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
25777 },
25778
25779 fromNow : function (withoutSuffix) {
25780 return this.from(moment(), withoutSuffix);
25781 },
25782
25783 calendar : function () {
25784 // We want to compare the start of today, vs this.
25785 // Getting start-of-today depends on whether we're zone'd or not.
25786 var sod = makeAs(moment(), this).startOf('day'),
25787 diff = this.diff(sod, 'days', true),
25788 format = diff < -6 ? 'sameElse' :
25789 diff < -1 ? 'lastWeek' :
25790 diff < 0 ? 'lastDay' :
25791 diff < 1 ? 'sameDay' :
25792 diff < 2 ? 'nextDay' :
25793 diff < 7 ? 'nextWeek' : 'sameElse';
25794 return this.format(this.lang().calendar(format, this));
25795 },
25796
25797 isLeapYear : function () {
25798 return isLeapYear(this.year());
25799 },
25800
25801 isDST : function () {
25802 return (this.zone() < this.clone().month(0).zone() ||
25803 this.zone() < this.clone().month(5).zone());
25804 },
25805
25806 day : function (input) {
25807 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
25808 if (input != null) {
25809 input = parseWeekday(input, this.lang());
25810 return this.add({ d : input - day });
25811 } else {
25812 return day;
25813 }
25814 },
25815
25816 month : function (input) {
25817 var utc = this._isUTC ? 'UTC' : '',
25818 dayOfMonth;
25819
25820 if (input != null) {
25821 if (typeof input === 'string') {
25822 input = this.lang().monthsParse(input);
25823 if (typeof input !== 'number') {
25824 return this;
25825 }
25826 }
25827
25828 dayOfMonth = this.date();
25829 this.date(1);
25830 this._d['set' + utc + 'Month'](input);
25831 this.date(Math.min(dayOfMonth, this.daysInMonth()));
25832
25833 moment.updateOffset(this);
25834 return this;
25835 } else {
25836 return this._d['get' + utc + 'Month']();
25837 }
25838 },
25839
25840 startOf: function (units) {
25841 units = normalizeUnits(units);
25842 // the following switch intentionally omits break keywords
25843 // to utilize falling through the cases.
25844 switch (units) {
25845 case 'year':
25846 this.month(0);
25847 /* falls through */
25848 case 'month':
25849 this.date(1);
25850 /* falls through */
25851 case 'week':
25852 case 'isoWeek':
25853 case 'day':
25854 this.hours(0);
25855 /* falls through */
25856 case 'hour':
25857 this.minutes(0);
25858 /* falls through */
25859 case 'minute':
25860 this.seconds(0);
25861 /* falls through */
25862 case 'second':
25863 this.milliseconds(0);
25864 /* falls through */
25865 }
25866
25867 // weeks are a special case
25868 if (units === 'week') {
25869 this.weekday(0);
25870 } else if (units === 'isoWeek') {
25871 this.isoWeekday(1);
25872 }
25873
25874 return this;
25875 },
25876
25877 endOf: function (units) {
25878 units = normalizeUnits(units);
25879 return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
25880 },
25881
25882 isAfter: function (input, units) {
25883 units = typeof units !== 'undefined' ? units : 'millisecond';
25884 return +this.clone().startOf(units) > +moment(input).startOf(units);
25885 },
25886
25887 isBefore: function (input, units) {
25888 units = typeof units !== 'undefined' ? units : 'millisecond';
25889 return +this.clone().startOf(units) < +moment(input).startOf(units);
25890 },
25891
25892 isSame: function (input, units) {
25893 units = units || 'ms';
25894 return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
25895 },
25896
25897 min: function (other) {
25898 other = moment.apply(null, arguments);
25899 return other < this ? this : other;
25900 },
25901
25902 max: function (other) {
25903 other = moment.apply(null, arguments);
25904 return other > this ? this : other;
25905 },
25906
25907 zone : function (input) {
25908 var offset = this._offset || 0;
25909 if (input != null) {
25910 if (typeof input === "string") {
25911 input = timezoneMinutesFromString(input);
25912 }
25913 if (Math.abs(input) < 16) {
25914 input = input * 60;
25915 }
25916 this._offset = input;
25917 this._isUTC = true;
25918 if (offset !== input) {
25919 addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
25920 }
25921 } else {
25922 return this._isUTC ? offset : this._d.getTimezoneOffset();
25923 }
25924 return this;
25925 },
25926
25927 zoneAbbr : function () {
25928 return this._isUTC ? "UTC" : "";
25929 },
25930
25931 zoneName : function () {
25932 return this._isUTC ? "Coordinated Universal Time" : "";
25933 },
25934
25935 parseZone : function () {
25936 if (this._tzm) {
25937 this.zone(this._tzm);
25938 } else if (typeof this._i === 'string') {
25939 this.zone(this._i);
25940 }
25941 return this;
25942 },
25943
25944 hasAlignedHourOffset : function (input) {
25945 if (!input) {
25946 input = 0;
25947 }
25948 else {
25949 input = moment(input).zone();
25950 }
25951
25952 return (this.zone() - input) % 60 === 0;
25953 },
25954
25955 daysInMonth : function () {
25956 return daysInMonth(this.year(), this.month());
25957 },
25958
25959 dayOfYear : function (input) {
25960 var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
25961 return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
25962 },
25963
25964 quarter : function () {
25965 return Math.ceil((this.month() + 1.0) / 3.0);
25966 },
25967
25968 weekYear : function (input) {
25969 var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
25970 return input == null ? year : this.add("y", (input - year));
25971 },
25972
25973 isoWeekYear : function (input) {
25974 var year = weekOfYear(this, 1, 4).year;
25975 return input == null ? year : this.add("y", (input - year));
25976 },
25977
25978 week : function (input) {
25979 var week = this.lang().week(this);
25980 return input == null ? week : this.add("d", (input - week) * 7);
25981 },
25982
25983 isoWeek : function (input) {
25984 var week = weekOfYear(this, 1, 4).week;
25985 return input == null ? week : this.add("d", (input - week) * 7);
25986 },
25987
25988 weekday : function (input) {
25989 var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
25990 return input == null ? weekday : this.add("d", input - weekday);
25991 },
25992
25993 isoWeekday : function (input) {
25994 // behaves the same as moment#day except
25995 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
25996 // as a setter, sunday should belong to the previous week.
25997 return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
25998 },
25999
26000 get : function (units) {
26001 units = normalizeUnits(units);
26002 return this[units]();
26003 },
26004
26005 set : function (units, value) {
26006 units = normalizeUnits(units);
26007 if (typeof this[units] === 'function') {
26008 this[units](value);
26009 }
26010 return this;
26011 },
26012
26013 // If passed a language key, it will set the language for this
26014 // instance. Otherwise, it will return the language configuration
26015 // variables for this instance.
26016 lang : function (key) {
26017 if (key === undefined) {
26018 return this._lang;
26019 } else {
26020 this._lang = getLangDefinition(key);
26021 return this;
26022 }
26023 }
26024 });
26025
26026 // helper for adding shortcuts
26027 function makeGetterAndSetter(name, key) {
26028 moment.fn[name] = moment.fn[name + 's'] = function (input) {
26029 var utc = this._isUTC ? 'UTC' : '';
26030 if (input != null) {
26031 this._d['set' + utc + key](input);
26032 moment.updateOffset(this);
26033 return this;
26034 } else {
26035 return this._d['get' + utc + key]();
26036 }
26037 };
26038 }
26039
26040 // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
26041 for (i = 0; i < proxyGettersAndSetters.length; i ++) {
26042 makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
26043 }
26044
26045 // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
26046 makeGetterAndSetter('year', 'FullYear');
26047
26048 // add plural methods
26049 moment.fn.days = moment.fn.day;
26050 moment.fn.months = moment.fn.month;
26051 moment.fn.weeks = moment.fn.week;
26052 moment.fn.isoWeeks = moment.fn.isoWeek;
26053
26054 // add aliased format methods
26055 moment.fn.toJSON = moment.fn.toISOString;
26056
26057 /************************************
26058 Duration Prototype
26059 ************************************/
26060
26061
26062 extend(moment.duration.fn = Duration.prototype, {
26063
26064 _bubble : function () {
26065 var milliseconds = this._milliseconds,
26066 days = this._days,
26067 months = this._months,
26068 data = this._data,
26069 seconds, minutes, hours, years;
26070
26071 // The following code bubbles up values, see the tests for
26072 // examples of what that means.
26073 data.milliseconds = milliseconds % 1000;
26074
26075 seconds = absRound(milliseconds / 1000);
26076 data.seconds = seconds % 60;
26077
26078 minutes = absRound(seconds / 60);
26079 data.minutes = minutes % 60;
26080
26081 hours = absRound(minutes / 60);
26082 data.hours = hours % 24;
26083
26084 days += absRound(hours / 24);
26085 data.days = days % 30;
26086
26087 months += absRound(days / 30);
26088 data.months = months % 12;
26089
26090 years = absRound(months / 12);
26091 data.years = years;
26092 },
26093
26094 weeks : function () {
26095 return absRound(this.days() / 7);
26096 },
26097
26098 valueOf : function () {
26099 return this._milliseconds +
26100 this._days * 864e5 +
26101 (this._months % 12) * 2592e6 +
26102 toInt(this._months / 12) * 31536e6;
26103 },
26104
26105 humanize : function (withSuffix) {
26106 var difference = +this,
26107 output = relativeTime(difference, !withSuffix, this.lang());
26108
26109 if (withSuffix) {
26110 output = this.lang().pastFuture(difference, output);
26111 }
26112
26113 return this.lang().postformat(output);
26114 },
26115
26116 add : function (input, val) {
26117 // supports only 2.0-style add(1, 's') or add(moment)
26118 var dur = moment.duration(input, val);
26119
26120 this._milliseconds += dur._milliseconds;
26121 this._days += dur._days;
26122 this._months += dur._months;
26123
26124 this._bubble();
26125
26126 return this;
26127 },
26128
26129 subtract : function (input, val) {
26130 var dur = moment.duration(input, val);
26131
26132 this._milliseconds -= dur._milliseconds;
26133 this._days -= dur._days;
26134 this._months -= dur._months;
26135
26136 this._bubble();
26137
26138 return this;
26139 },
26140
26141 get : function (units) {
26142 units = normalizeUnits(units);
26143 return this[units.toLowerCase() + 's']();
26144 },
26145
26146 as : function (units) {
26147 units = normalizeUnits(units);
26148 return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
26149 },
26150
26151 lang : moment.fn.lang,
26152
26153 toIsoString : function () {
26154 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
26155 var years = Math.abs(this.years()),
26156 months = Math.abs(this.months()),
26157 days = Math.abs(this.days()),
26158 hours = Math.abs(this.hours()),
26159 minutes = Math.abs(this.minutes()),
26160 seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
26161
26162 if (!this.asSeconds()) {
26163 // this is the same as C#'s (Noda) and python (isodate)...
26164 // but not other JS (goog.date)
26165 return 'P0D';
26166 }
26167
26168 return (this.asSeconds() < 0 ? '-' : '') +
26169 'P' +
26170 (years ? years + 'Y' : '') +
26171 (months ? months + 'M' : '') +
26172 (days ? days + 'D' : '') +
26173 ((hours || minutes || seconds) ? 'T' : '') +
26174 (hours ? hours + 'H' : '') +
26175 (minutes ? minutes + 'M' : '') +
26176 (seconds ? seconds + 'S' : '');
26177 }
26178 });
26179
26180 function makeDurationGetter(name) {
26181 moment.duration.fn[name] = function () {
26182 return this._data[name];
26183 };
26184 }
26185
26186 function makeDurationAsGetter(name, factor) {
26187 moment.duration.fn['as' + name] = function () {
26188 return +this / factor;
26189 };
26190 }
26191
26192 for (i in unitMillisecondFactors) {
26193 if (unitMillisecondFactors.hasOwnProperty(i)) {
26194 makeDurationAsGetter(i, unitMillisecondFactors[i]);
26195 makeDurationGetter(i.toLowerCase());
26196 }
26197 }
26198
26199 makeDurationAsGetter('Weeks', 6048e5);
26200 moment.duration.fn.asMonths = function () {
26201 return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
26202 };
26203
26204
26205 /************************************
26206 Default Lang
26207 ************************************/
26208
26209
26210 // Set default language, other languages will inherit from English.
26211 moment.lang('en', {
26212 ordinal : function (number) {
26213 var b = number % 10,
26214 output = (toInt(number % 100 / 10) === 1) ? 'th' :
26215 (b === 1) ? 'st' :
26216 (b === 2) ? 'nd' :
26217 (b === 3) ? 'rd' : 'th';
26218 return number + output;
26219 }
26220 });
26221
26222 /* EMBED_LANGUAGES */
26223
26224 /************************************
26225 Exposing Moment
26226 ************************************/
26227
26228 function makeGlobal(deprecate) {
26229 var warned = false, local_moment = moment;
26230 /*global ender:false */
26231 if (typeof ender !== 'undefined') {
26232 return;
26233 }
26234 // here, `this` means `window` in the browser, or `global` on the server
26235 // add `moment` as a global object via a string identifier,
26236 // for Closure Compiler "advanced" mode
26237 if (deprecate) {
26238 global.moment = function () {
26239 if (!warned && console && console.warn) {
26240 warned = true;
26241 console.warn(
26242 "Accessing Moment through the global scope is " +
26243 "deprecated, and will be removed in an upcoming " +
26244 "release.");
26245 }
26246 return local_moment.apply(null, arguments);
26247 };
26248 extend(global.moment, local_moment);
26249 } else {
26250 global['moment'] = moment;
26251 }
26252 }
26253
26254 // CommonJS module is defined
26255 if (hasModule) {
26256 module.exports = moment;
26257 makeGlobal(true);
26258 } else if (typeof define === "function" && define.amd) {
26259 define("moment", function (require, exports, module) {
26260 if (module.config && module.config() && module.config().noGlobal !== true) {
26261 // If user provided noGlobal, he is aware of global
26262 makeGlobal(module.config().noGlobal === undefined);
26263 }
26264
26265 return moment;
26266 });
26267 } else {
26268 makeGlobal();
26269 }
26270 }).call(this);
26271 /*!
26272 * UCSV 1.1.0
26273 * Provided under MIT License.
26274 *
26275 * Copyright 2010-2012, Peter Johnson
26276 * http://www.uselesscode.org/javascript/csv/
26277 */
26278 var CSV=(function(){var f=/^\d+$/,g=/^\d*\.\d+$|^\d+\.\d*$/,i=/^\s|\s$|,|"|\n/,b=(function(){if(String.prototype.trim){return function(j){return j.trim()}}else{return function(j){return j.replace(/^\s*/,"").replace(/\s*$/,"")}}}());function h(j){return Object.prototype.toString.apply(j)==="[object Number]"}function a(j){return Object.prototype.toString.apply(j)==="[object String]"}function d(j){if(j.charAt(j.length-1)!=="\n"){return j}else{return j.substring(0,j.length-1)}}function e(k){var p,m="",o,n,l;for(n=0;n<k.length;n+=1){o=k[n];for(l=0;l<o.length;l+=1){p=o[l];if(a(p)){p=p.replace(/"/g,'""');if(i.test(p)||f.test(p)||g.test(p)){p='"'+p+'"'}else{if(p===""){p='""'}}}else{if(h(p)){p=p.toString(10)}else{if(p===null){p=""}else{p=p.toString()}}}m+=l<o.length-1?p+",":p}m+="\n"}return m}function c(t,p){t=d(t);var q="",l=false,m=false,o="",r=[],j=[],k,n;n=function(s){if(m!==true){if(s===""){s=null}else{if(p===true){s=b(s)}}if(f.test(s)){s=parseInt(s,10)}else{if(g.test(s)){s=parseFloat(s,10)}}}return s};for(k=0;k<t.length;k+=1){q=t.charAt(k);if(l===false&&(q===","||q==="\n")){o=n(o);r.push(o);if(q==="\n"){j.push(r);r=[]}o="";m=false}else{if(q!=='"'){o+=q}else{if(!l){l=true;m=true}else{if(t.charAt(k+1)==='"'){o+='"';k+=1}else{l=false}}}}}o=n(o);r.push(o);j.push(r);return j}if(typeof exports==="object"){exports.arrayToCsv=e;exports.csvToArray=c}return{arrayToCsv:e,csvToArray:c}}());
26279 /* Javascript plotting library for jQuery, version 0.8.3-alpha.
26280
26281 Copyright (c) 2007-2013 IOLA and Ole Laursen.
26282 Licensed under the MIT license.
26283
26284 */
26285
26286 // first an inline dependency, jquery.colorhelpers.js, we inline it here
26287 // for convenience
26288
26289 /* Plugin for jQuery for working with colors.
26290 *
26291 * Version 1.1.
26292 *
26293 * Inspiration from jQuery color animation plugin by John Resig.
26294 *
26295 * Released under the MIT license by Ole Laursen, October 2009.
26296 *
26297 * Examples:
26298 *
26299 * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
26300 * var c = $.color.extract($("#mydiv"), 'background-color');
26301 * console.log(c.r, c.g, c.b, c.a);
26302 * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
26303 *
26304 * Note that .scale() and .add() return the same modified object
26305 * instead of making a new one.
26306 *
26307 * V. 1.1: Fix error handling so e.g. parsing an empty string does
26308 * produce a color rather than just crashing.
26309 */
26310 (function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);
26311
26312 // the actual Flot code
26313 (function($) {
26314
26315 // Cache the prototype hasOwnProperty for faster access
26316
26317 var hasOwnProperty = Object.prototype.hasOwnProperty;
26318
26319 ///////////////////////////////////////////////////////////////////////////
26320 // The Canvas object is a wrapper around an HTML5 <canvas> tag.
26321 //
26322 // @constructor
26323 // @param {string} cls List of classes to apply to the canvas.
26324 // @param {element} container Element onto which to append the canvas.
26325 //
26326 // Requiring a container is a little iffy, but unfortunately canvas
26327 // operations don't work unless the canvas is attached to the DOM.
26328
26329 function Canvas(cls, container) {
26330
26331 var element = container.children("." + cls)[0];
26332
26333 if (element == null) {
26334
26335 element = document.createElement("canvas");
26336 element.className = cls;
26337
26338 $(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 })
26339 .appendTo(container);
26340
26341 // If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas
26342
26343 if (!element.getContext) {
26344 if (window.G_vmlCanvasManager) {
26345 element = window.G_vmlCanvasManager.initElement(element);
26346 } else {
26347 throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");
26348 }
26349 }
26350 }
26351
26352 this.element = element;
26353
26354 var context = this.context = element.getContext("2d");
26355
26356 // Determine the screen's ratio of physical to device-independent
26357 // pixels. This is the ratio between the canvas width that the browser
26358 // advertises and the number of pixels actually present in that space.
26359
26360 // The iPhone 4, for example, has a device-independent width of 320px,
26361 // but its screen is actually 640px wide. It therefore has a pixel
26362 // ratio of 2, while most normal devices have a ratio of 1.
26363
26364 var devicePixelRatio = window.devicePixelRatio || 1,
26365 backingStoreRatio =
26366 context.webkitBackingStorePixelRatio ||
26367 context.mozBackingStorePixelRatio ||
26368 context.msBackingStorePixelRatio ||
26369 context.oBackingStorePixelRatio ||
26370 context.backingStorePixelRatio || 1;
26371
26372 this.pixelRatio = devicePixelRatio / backingStoreRatio;
26373
26374 // Size the canvas to match the internal dimensions of its container
26375
26376 this.resize(container.width(), container.height());
26377
26378 // Collection of HTML div layers for text overlaid onto the canvas
26379
26380 this.textContainer = null;
26381 this.text = {};
26382
26383 // Cache of text fragments and metrics, so we can avoid expensively
26384 // re-calculating them when the plot is re-rendered in a loop.
26385
26386 this._textCache = {};
26387 }
26388
26389 // Resizes the canvas to the given dimensions.
26390 //
26391 // @param {number} width New width of the canvas, in pixels.
26392 // @param {number} width New height of the canvas, in pixels.
26393
26394 Canvas.prototype.resize = function(width, height) {
26395
26396 if (width <= 0 || height <= 0) {
26397 throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height);
26398 }
26399
26400 var element = this.element,
26401 context = this.context,
26402 pixelRatio = this.pixelRatio;
26403
26404 // Resize the canvas, increasing its density based on the display's
26405 // pixel ratio; basically giving it more pixels without increasing the
26406 // size of its element, to take advantage of the fact that retina
26407 // displays have that many more pixels in the same advertised space.
26408
26409 // Resizing should reset the state (excanvas seems to be buggy though)
26410
26411 if (this.width != width) {
26412 element.width = width * pixelRatio;
26413 element.style.width = width + "px";
26414 this.width = width;
26415 }
26416
26417 if (this.height != height) {
26418 element.height = height * pixelRatio;
26419 element.style.height = height + "px";
26420 this.height = height;
26421 }
26422
26423 // Save the context, so we can reset in case we get replotted. The
26424 // restore ensure that we're really back at the initial state, and
26425 // should be safe even if we haven't saved the initial state yet.
26426
26427 context.restore();
26428 context.save();
26429
26430 // Scale the coordinate space to match the display density; so even though we
26431 // may have twice as many pixels, we still want lines and other drawing to
26432 // appear at the same size; the extra pixels will just make them crisper.
26433
26434 context.scale(pixelRatio, pixelRatio);
26435 };
26436
26437 // Clears the entire canvas area, not including any overlaid HTML text
26438
26439 Canvas.prototype.clear = function() {
26440 this.context.clearRect(0, 0, this.width, this.height);
26441 };
26442
26443 // Finishes rendering the canvas, including managing the text overlay.
26444
26445 Canvas.prototype.render = function() {
26446
26447 var cache = this._textCache;
26448
26449 // For each text layer, add elements marked as active that haven't
26450 // already been rendered, and remove those that are no longer active.
26451
26452 for (var layerKey in cache) {
26453 if (hasOwnProperty.call(cache, layerKey)) {
26454
26455 var layer = this.getTextLayer(layerKey),
26456 layerCache = cache[layerKey];
26457
26458 layer.hide();
26459
26460 for (var styleKey in layerCache) {
26461 if (hasOwnProperty.call(layerCache, styleKey)) {
26462 var styleCache = layerCache[styleKey];
26463 for (var key in styleCache) {
26464 if (hasOwnProperty.call(styleCache, key)) {
26465
26466 var positions = styleCache[key].positions;
26467
26468 for (var i = 0, position; position = positions[i]; i++) {
26469 if (position.active) {
26470 if (!position.rendered) {
26471 layer.append(position.element);
26472 position.rendered = true;
26473 }
26474 } else {
26475 positions.splice(i--, 1);
26476 if (position.rendered) {
26477 position.element.detach();
26478 }
26479 }
26480 }
26481
26482 if (positions.length == 0) {
26483 delete styleCache[key];
26484 }
26485 }
26486 }
26487 }
26488 }
26489
26490 layer.show();
26491 }
26492 }
26493 };
26494
26495 // Creates (if necessary) and returns the text overlay container.
26496 //
26497 // @param {string} classes String of space-separated CSS classes used to
26498 // uniquely identify the text layer.
26499 // @return {object} The jQuery-wrapped text-layer div.
26500
26501 Canvas.prototype.getTextLayer = function(classes) {
26502
26503 var layer = this.text[classes];
26504
26505 // Create the text layer if it doesn't exist
26506
26507 if (layer == null) {
26508
26509 // Create the text layer container, if it doesn't exist
26510
26511 if (this.textContainer == null) {
26512 this.textContainer = $("<div class='flot-text'></div>")
26513 .css({
26514 position: "absolute",
26515 top: 0,
26516 left: 0,
26517 bottom: 0,
26518 right: 0,
26519 'font-size': "smaller",
26520 color: "#545454"
26521 })
26522 .insertAfter(this.element);
26523 }
26524
26525 layer = this.text[classes] = $("<div></div>")
26526 .addClass(classes)
26527 .css({
26528 position: "absolute",
26529 top: 0,
26530 left: 0,
26531 bottom: 0,
26532 right: 0
26533 })
26534 .appendTo(this.textContainer);
26535 }
26536
26537 return layer;
26538 };
26539
26540 // Creates (if necessary) and returns a text info object.
26541 //
26542 // The object looks like this:
26543 //
26544 // {
26545 // width: Width of the text's wrapper div.
26546 // height: Height of the text's wrapper div.
26547 // element: The jQuery-wrapped HTML div containing the text.
26548 // positions: Array of positions at which this text is drawn.
26549 // }
26550 //
26551 // The positions array contains objects that look like this:
26552 //
26553 // {
26554 // active: Flag indicating whether the text should be visible.
26555 // rendered: Flag indicating whether the text is currently visible.
26556 // element: The jQuery-wrapped HTML div containing the text.
26557 // x: X coordinate at which to draw the text.
26558 // y: Y coordinate at which to draw the text.
26559 // }
26560 //
26561 // Each position after the first receives a clone of the original element.
26562 //
26563 // The idea is that that the width, height, and general 'identity' of the
26564 // text is constant no matter where it is placed; the placements are a
26565 // secondary property.
26566 //
26567 // Canvas maintains a cache of recently-used text info objects; getTextInfo
26568 // either returns the cached element or creates a new entry.
26569 //
26570 // @param {string} layer A string of space-separated CSS classes uniquely
26571 // identifying the layer containing this text.
26572 // @param {string} text Text string to retrieve info for.
26573 // @param {(string|object)=} font Either a string of space-separated CSS
26574 // classes or a font-spec object, defining the text's font and style.
26575 // @param {number=} angle Angle at which to rotate the text, in degrees.
26576 // Angle is currently unused, it will be implemented in the future.
26577 // @param {number=} width Maximum width of the text before it wraps.
26578 // @return {object} a text info object.
26579
26580 Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) {
26581
26582 var textStyle, layerCache, styleCache, info;
26583
26584 // Cast the value to a string, in case we were given a number or such
26585
26586 text = "" + text;
26587
26588 // If the font is a font-spec object, generate a CSS font definition
26589
26590 if (typeof font === "object") {
26591 textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family;
26592 } else {
26593 textStyle = font;
26594 }
26595
26596 // Retrieve (or create) the cache for the text's layer and styles
26597
26598 layerCache = this._textCache[layer];
26599
26600 if (layerCache == null) {
26601 layerCache = this._textCache[layer] = {};
26602 }
26603
26604 styleCache = layerCache[textStyle];
26605
26606 if (styleCache == null) {
26607 styleCache = layerCache[textStyle] = {};
26608 }
26609
26610 info = styleCache[text];
26611
26612 // If we can't find a matching element in our cache, create a new one
26613
26614 if (info == null) {
26615
26616 var element = $("<div></div>").html(text)
26617 .css({
26618 position: "absolute",
26619 'max-width': width,
26620 top: -9999
26621 })
26622 .appendTo(this.getTextLayer(layer));
26623
26624 if (typeof font === "object") {
26625 element.css({
26626 font: textStyle,
26627 color: font.color
26628 });
26629 } else if (typeof font === "string") {
26630 element.addClass(font);
26631 }
26632
26633 info = styleCache[text] = {
26634 width: element.outerWidth(true),
26635 height: element.outerHeight(true),
26636 element: element,
26637 positions: []
26638 };
26639
26640 element.detach();
26641 }
26642
26643 return info;
26644 };
26645
26646 // Adds a text string to the canvas text overlay.
26647 //
26648 // The text isn't drawn immediately; it is marked as rendering, which will
26649 // result in its addition to the canvas on the next render pass.
26650 //
26651 // @param {string} layer A string of space-separated CSS classes uniquely
26652 // identifying the layer containing this text.
26653 // @param {number} x X coordinate at which to draw the text.
26654 // @param {number} y Y coordinate at which to draw the text.
26655 // @param {string} text Text string to draw.
26656 // @param {(string|object)=} font Either a string of space-separated CSS
26657 // classes or a font-spec object, defining the text's font and style.
26658 // @param {number=} angle Angle at which to rotate the text, in degrees.
26659 // Angle is currently unused, it will be implemented in the future.
26660 // @param {number=} width Maximum width of the text before it wraps.
26661 // @param {string=} halign Horizontal alignment of the text; either "left",
26662 // "center" or "right".
26663 // @param {string=} valign Vertical alignment of the text; either "top",
26664 // "middle" or "bottom".
26665
26666 Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {
26667
26668 var info = this.getTextInfo(layer, text, font, angle, width),
26669 positions = info.positions;
26670
26671 // Tweak the div's position to match the text's alignment
26672
26673 if (halign == "center") {
26674 x -= info.width / 2;
26675 } else if (halign == "right") {
26676 x -= info.width;
26677 }
26678
26679 if (valign == "middle") {
26680 y -= info.height / 2;
26681 } else if (valign == "bottom") {
26682 y -= info.height;
26683 }
26684
26685 // Determine whether this text already exists at this position.
26686 // If so, mark it for inclusion in the next render pass.
26687
26688 for (var i = 0, position; position = positions[i]; i++) {
26689 if (position.x == x && position.y == y) {
26690 position.active = true;
26691 return;
26692 }
26693 }
26694
26695 // If the text doesn't exist at this position, create a new entry
26696
26697 // For the very first position we'll re-use the original element,
26698 // while for subsequent ones we'll clone it.
26699
26700 position = {
26701 active: true,
26702 rendered: false,
26703 element: positions.length ? info.element.clone() : info.element,
26704 x: x,
26705 y: y
26706 };
26707
26708 positions.push(position);
26709
26710 // Move the element to its final position within the container
26711
26712 position.element.css({
26713 top: Math.round(y),
26714 left: Math.round(x),
26715 'text-align': halign // In case the text wraps
26716 });
26717 };
26718
26719 // Removes one or more text strings from the canvas text overlay.
26720 //
26721 // If no parameters are given, all text within the layer is removed.
26722 //
26723 // Note that the text is not immediately removed; it is simply marked as
26724 // inactive, which will result in its removal on the next render pass.
26725 // This avoids the performance penalty for 'clear and redraw' behavior,
26726 // where we potentially get rid of all text on a layer, but will likely
26727 // add back most or all of it later, as when redrawing axes, for example.
26728 //
26729 // @param {string} layer A string of space-separated CSS classes uniquely
26730 // identifying the layer containing this text.
26731 // @param {number=} x X coordinate of the text.
26732 // @param {number=} y Y coordinate of the text.
26733 // @param {string=} text Text string to remove.
26734 // @param {(string|object)=} font Either a string of space-separated CSS
26735 // classes or a font-spec object, defining the text's font and style.
26736 // @param {number=} angle Angle at which the text is rotated, in degrees.
26737 // Angle is currently unused, it will be implemented in the future.
26738
26739 Canvas.prototype.removeText = function(layer, x, y, text, font, angle) {
26740 if (text == null) {
26741 var layerCache = this._textCache[layer];
26742 if (layerCache != null) {
26743 for (var styleKey in layerCache) {
26744 if (hasOwnProperty.call(layerCache, styleKey)) {
26745 var styleCache = layerCache[styleKey];
26746 for (var key in styleCache) {
26747 if (hasOwnProperty.call(styleCache, key)) {
26748 var positions = styleCache[key].positions;
26749 for (var i = 0, position; position = positions[i]; i++) {
26750 position.active = false;
26751 }
26752 }
26753 }
26754 }
26755 }
26756 }
26757 } else {
26758 var positions = this.getTextInfo(layer, text, font, angle).positions;
26759 for (var i = 0, position; position = positions[i]; i++) {
26760 if (position.x == x && position.y == y) {
26761 position.active = false;
26762 }
26763 }
26764 }
26765 };
26766
26767 ///////////////////////////////////////////////////////////////////////////
26768 // The top-level container for the entire plot.
26769
26770 function Plot(placeholder, data_, options_, plugins) {
26771 // data is on the form:
26772 // [ series1, series2 ... ]
26773 // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
26774 // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
26775
26776 var series = [],
26777 options = {
26778 // the color theme used for graphs
26779 colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
26780 legend: {
26781 show: true,
26782 noColumns: 1, // number of colums in legend table
26783 labelFormatter: null, // fn: string -> string
26784 labelBoxBorderColor: "#ccc", // border color for the little label boxes
26785 container: null, // container (as jQuery object) to put legend in, null means default on top of graph
26786 position: "ne", // position of default legend container within plot
26787 margin: 5, // distance from grid edge to default legend container within plot
26788 backgroundColor: null, // null means auto-detect
26789 backgroundOpacity: 0.85, // set to 0 to avoid background
26790 sorted: null // default to no legend sorting
26791 },
26792 xaxis: {
26793 show: null, // null = auto-detect, true = always, false = never
26794 position: "bottom", // or "top"
26795 mode: null, // null or "time"
26796 font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
26797 color: null, // base color, labels, ticks
26798 tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
26799 transform: null, // null or f: number -> number to transform axis
26800 inverseTransform: null, // if transform is set, this should be the inverse function
26801 min: null, // min. value to show, null means set automatically
26802 max: null, // max. value to show, null means set automatically
26803 autoscaleMargin: null, // margin in % to add if auto-setting min/max
26804 ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
26805 tickFormatter: null, // fn: number -> string
26806 labelWidth: null, // size of tick labels in pixels
26807 labelHeight: null,
26808 reserveSpace: null, // whether to reserve space even if axis isn't shown
26809 tickLength: null, // size in pixels of ticks, or "full" for whole line
26810 alignTicksWithAxis: null, // axis number or null for no sync
26811 tickDecimals: null, // no. of decimals, null means auto
26812 tickSize: null, // number or [number, "unit"]
26813 minTickSize: null // number or [number, "unit"]
26814 },
26815 yaxis: {
26816 autoscaleMargin: 0.02,
26817 position: "left" // or "right"
26818 },
26819 xaxes: [],
26820 yaxes: [],
26821 series: {
26822 points: {
26823 show: false,
26824 radius: 3,
26825 lineWidth: 2, // in pixels
26826 fill: true,
26827 fillColor: "#ffffff",
26828 symbol: "circle" // or callback
26829 },
26830 lines: {
26831 // we don't put in show: false so we can see
26832 // whether lines were actively disabled
26833 lineWidth: 2, // in pixels
26834 fill: false,
26835 fillColor: null,
26836 steps: false
26837 // Omit 'zero', so we can later default its value to
26838 // match that of the 'fill' option.
26839 },
26840 bars: {
26841 show: false,
26842 lineWidth: 2, // in pixels
26843 barWidth: 1, // in units of the x axis
26844 fill: true,
26845 fillColor: null,
26846 align: "left", // "left", "right", or "center"
26847 horizontal: false,
26848 zero: true
26849 },
26850 shadowSize: 3,
26851 highlightColor: null
26852 },
26853 grid: {
26854 show: true,
26855 aboveData: false,
26856 color: "#545454", // primary color used for outline and labels
26857 backgroundColor: null, // null for transparent, else color
26858 borderColor: null, // set if different from the grid color
26859 tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"
26860 margin: 0, // distance from the canvas edge to the grid
26861 labelMargin: 5, // in pixels
26862 axisMargin: 8, // in pixels
26863 borderWidth: 2, // in pixels
26864 minBorderMargin: null, // in pixels, null means taken from points radius
26865 markings: null, // array of ranges or fn: axes -> array of ranges
26866 markingsColor: "#f4f4f4",
26867 markingsLineWidth: 2,
26868 // interactive stuff
26869 clickable: false,
26870 hoverable: false,
26871 autoHighlight: true, // highlight in case mouse is near
26872 mouseActiveRadius: 10 // how far the mouse can be away to activate an item
26873 },
26874 interaction: {
26875 redrawOverlayInterval: 1000/60 // time between updates, -1 means in same flow
26876 },
26877 hooks: {}
26878 },
26879 surface = null, // the canvas for the plot itself
26880 overlay = null, // canvas for interactive stuff on top of plot
26881 eventHolder = null, // jQuery object that events should be bound to
26882 ctx = null, octx = null,
26883 xaxes = [], yaxes = [],
26884 plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
26885 plotWidth = 0, plotHeight = 0,
26886 hooks = {
26887 processOptions: [],
26888 processRawData: [],
26889 processDatapoints: [],
26890 processOffset: [],
26891 drawBackground: [],
26892 drawSeries: [],
26893 draw: [],
26894 bindEvents: [],
26895 drawOverlay: [],
26896 shutdown: []
26897 },
26898 plot = this;
26899
26900 // public functions
26901 plot.setData = setData;
26902 plot.setupGrid = setupGrid;
26903 plot.draw = draw;
26904 plot.getPlaceholder = function() { return placeholder; };
26905 plot.getCanvas = function() { return surface.element; };
26906 plot.getPlotOffset = function() { return plotOffset; };
26907 plot.width = function () { return plotWidth; };
26908 plot.height = function () { return plotHeight; };
26909 plot.offset = function () {
26910 var o = eventHolder.offset();
26911 o.left += plotOffset.left;
26912 o.top += plotOffset.top;
26913 return o;
26914 };
26915 plot.getData = function () { return series; };
26916 plot.getAxes = function () {
26917 var res = {}, i;
26918 $.each(xaxes.concat(yaxes), function (_, axis) {
26919 if (axis)
26920 res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
26921 });
26922 return res;
26923 };
26924 plot.getXAxes = function () { return xaxes; };
26925 plot.getYAxes = function () { return yaxes; };
26926 plot.c2p = canvasToAxisCoords;
26927 plot.p2c = axisToCanvasCoords;
26928 plot.getOptions = function () { return options; };
26929 plot.highlight = highlight;
26930 plot.unhighlight = unhighlight;
26931 plot.triggerRedrawOverlay = triggerRedrawOverlay;
26932 plot.pointOffset = function(point) {
26933 return {
26934 left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left, 10),
26935 top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10)
26936 };
26937 };
26938 plot.shutdown = shutdown;
26939 plot.destroy = function () {
26940 shutdown();
26941 placeholder.removeData("plot").empty();
26942
26943 series = [];
26944 options = null;
26945 surface = null;
26946 overlay = null;
26947 eventHolder = null;
26948 ctx = null;
26949 octx = null;
26950 xaxes = [];
26951 yaxes = [];
26952 hooks = null;
26953 highlights = [];
26954 plot = null;
26955 };
26956 plot.resize = function () {
26957 var width = placeholder.width(),
26958 height = placeholder.height();
26959 surface.resize(width, height);
26960 overlay.resize(width, height);
26961 };
26962
26963 // public attributes
26964 plot.hooks = hooks;
26965
26966 // initialize
26967 initPlugins(plot);
26968 parseOptions(options_);
26969 setupCanvases();
26970 setData(data_);
26971 setupGrid();
26972 draw();
26973 bindEvents();
26974
26975
26976 function executeHooks(hook, args) {
26977 args = [plot].concat(args);
26978 for (var i = 0; i < hook.length; ++i)
26979 hook[i].apply(this, args);
26980 }
26981
26982 function initPlugins() {
26983
26984 // References to key classes, allowing plugins to modify them
26985
26986 var classes = {
26987 Canvas: Canvas
26988 };
26989
26990 for (var i = 0; i < plugins.length; ++i) {
26991 var p = plugins[i];
26992 p.init(plot, classes);
26993 if (p.options)
26994 $.extend(true, options, p.options);
26995 }
26996 }
26997
26998 function parseOptions(opts) {
26999
27000 $.extend(true, options, opts);
27001
27002 // $.extend merges arrays, rather than replacing them. When less
27003 // colors are provided than the size of the default palette, we
27004 // end up with those colors plus the remaining defaults, which is
27005 // not expected behavior; avoid it by replacing them here.
27006
27007 if (opts && opts.colors) {
27008 options.colors = opts.colors;
27009 }
27010
27011 if (options.xaxis.color == null)
27012 options.xaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
27013 if (options.yaxis.color == null)
27014 options.yaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
27015
27016 if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility
27017 options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color;
27018 if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility
27019 options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color;
27020
27021 if (options.grid.borderColor == null)
27022 options.grid.borderColor = options.grid.color;
27023 if (options.grid.tickColor == null)
27024 options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
27025
27026 // Fill in defaults for axis options, including any unspecified
27027 // font-spec fields, if a font-spec was provided.
27028
27029 // If no x/y axis options were provided, create one of each anyway,
27030 // since the rest of the code assumes that they exist.
27031
27032 var i, axisOptions, axisCount,
27033 fontSize = placeholder.css("font-size"),
27034 fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13,
27035 fontDefaults = {
27036 style: placeholder.css("font-style"),
27037 size: Math.round(0.8 * fontSizeDefault),
27038 variant: placeholder.css("font-variant"),
27039 weight: placeholder.css("font-weight"),
27040 family: placeholder.css("font-family")
27041 };
27042
27043 axisCount = options.xaxes.length || 1;
27044 for (i = 0; i < axisCount; ++i) {
27045
27046 axisOptions = options.xaxes[i];
27047 if (axisOptions && !axisOptions.tickColor) {
27048 axisOptions.tickColor = axisOptions.color;
27049 }
27050
27051 axisOptions = $.extend(true, {}, options.xaxis, axisOptions);
27052 options.xaxes[i] = axisOptions;
27053
27054 if (axisOptions.font) {
27055 axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
27056 if (!axisOptions.font.color) {
27057 axisOptions.font.color = axisOptions.color;
27058 }
27059 if (!axisOptions.font.lineHeight) {
27060 axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
27061 }
27062 }
27063 }
27064
27065 axisCount = options.yaxes.length || 1;
27066 for (i = 0; i < axisCount; ++i) {
27067
27068 axisOptions = options.yaxes[i];
27069 if (axisOptions && !axisOptions.tickColor) {
27070 axisOptions.tickColor = axisOptions.color;
27071 }
27072
27073 axisOptions = $.extend(true, {}, options.yaxis, axisOptions);
27074 options.yaxes[i] = axisOptions;
27075
27076 if (axisOptions.font) {
27077 axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
27078 if (!axisOptions.font.color) {
27079 axisOptions.font.color = axisOptions.color;
27080 }
27081 if (!axisOptions.font.lineHeight) {
27082 axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
27083 }
27084 }
27085 }
27086
27087 // backwards compatibility, to be removed in future
27088 if (options.xaxis.noTicks && options.xaxis.ticks == null)
27089 options.xaxis.ticks = options.xaxis.noTicks;
27090 if (options.yaxis.noTicks && options.yaxis.ticks == null)
27091 options.yaxis.ticks = options.yaxis.noTicks;
27092 if (options.x2axis) {
27093 options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
27094 options.xaxes[1].position = "top";
27095 }
27096 if (options.y2axis) {
27097 options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
27098 options.yaxes[1].position = "right";
27099 }
27100 if (options.grid.coloredAreas)
27101 options.grid.markings = options.grid.coloredAreas;
27102 if (options.grid.coloredAreasColor)
27103 options.grid.markingsColor = options.grid.coloredAreasColor;
27104 if (options.lines)
27105 $.extend(true, options.series.lines, options.lines);
27106 if (options.points)
27107 $.extend(true, options.series.points, options.points);
27108 if (options.bars)
27109 $.extend(true, options.series.bars, options.bars);
27110 if (options.shadowSize != null)
27111 options.series.shadowSize = options.shadowSize;
27112 if (options.highlightColor != null)
27113 options.series.highlightColor = options.highlightColor;
27114
27115 // save options on axes for future reference
27116 for (i = 0; i < options.xaxes.length; ++i)
27117 getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
27118 for (i = 0; i < options.yaxes.length; ++i)
27119 getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
27120
27121 // add hooks from options
27122 for (var n in hooks)
27123 if (options.hooks[n] && options.hooks[n].length)
27124 hooks[n] = hooks[n].concat(options.hooks[n]);
27125
27126 executeHooks(hooks.processOptions, [options]);
27127 }
27128
27129 function setData(d) {
27130 series = parseData(d);
27131 fillInSeriesOptions();
27132 processData();
27133 }
27134
27135 function parseData(d) {
27136 var res = [];
27137 for (var i = 0; i < d.length; ++i) {
27138 var s = $.extend(true, {}, options.series);
27139
27140 if (d[i].data != null) {
27141 s.data = d[i].data; // move the data instead of deep-copy
27142 delete d[i].data;
27143
27144 $.extend(true, s, d[i]);
27145
27146 d[i].data = s.data;
27147 }
27148 else
27149 s.data = d[i];
27150 res.push(s);
27151 }
27152
27153 return res;
27154 }
27155
27156 function axisNumber(obj, coord) {
27157 var a = obj[coord + "axis"];
27158 if (typeof a == "object") // if we got a real axis, extract number
27159 a = a.n;
27160 if (typeof a != "number")
27161 a = 1; // default to first axis
27162 return a;
27163 }
27164
27165 function allAxes() {
27166 // return flat array without annoying null entries
27167 return $.grep(xaxes.concat(yaxes), function (a) { return a; });
27168 }
27169
27170 function canvasToAxisCoords(pos) {
27171 // return an object with x/y corresponding to all used axes
27172 var res = {}, i, axis;
27173 for (i = 0; i < xaxes.length; ++i) {
27174 axis = xaxes[i];
27175 if (axis && axis.used)
27176 res["x" + axis.n] = axis.c2p(pos.left);
27177 }
27178
27179 for (i = 0; i < yaxes.length; ++i) {
27180 axis = yaxes[i];
27181 if (axis && axis.used)
27182 res["y" + axis.n] = axis.c2p(pos.top);
27183 }
27184
27185 if (res.x1 !== undefined)
27186 res.x = res.x1;
27187 if (res.y1 !== undefined)
27188 res.y = res.y1;
27189
27190 return res;
27191 }
27192
27193 function axisToCanvasCoords(pos) {
27194 // get canvas coords from the first pair of x/y found in pos
27195 var res = {}, i, axis, key;
27196
27197 for (i = 0; i < xaxes.length; ++i) {
27198 axis = xaxes[i];
27199 if (axis && axis.used) {
27200 key = "x" + axis.n;
27201 if (pos[key] == null && axis.n == 1)
27202 key = "x";
27203
27204 if (pos[key] != null) {
27205 res.left = axis.p2c(pos[key]);
27206 break;
27207 }
27208 }
27209 }
27210
27211 for (i = 0; i < yaxes.length; ++i) {
27212 axis = yaxes[i];
27213 if (axis && axis.used) {
27214 key = "y" + axis.n;
27215 if (pos[key] == null && axis.n == 1)
27216 key = "y";
27217
27218 if (pos[key] != null) {
27219 res.top = axis.p2c(pos[key]);
27220 break;
27221 }
27222 }
27223 }
27224
27225 return res;
27226 }
27227
27228 function getOrCreateAxis(axes, number) {
27229 if (!axes[number - 1])
27230 axes[number - 1] = {
27231 n: number, // save the number for future reference
27232 direction: axes == xaxes ? "x" : "y",
27233 options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
27234 };
27235
27236 return axes[number - 1];
27237 }
27238
27239 function fillInSeriesOptions() {
27240
27241 var neededColors = series.length, maxIndex = -1, i;
27242
27243 // Subtract the number of series that already have fixed colors or
27244 // color indexes from the number that we still need to generate.
27245
27246 for (i = 0; i < series.length; ++i) {
27247 var sc = series[i].color;
27248 if (sc != null) {
27249 neededColors--;
27250 if (typeof sc == "number" && sc > maxIndex) {
27251 maxIndex = sc;
27252 }
27253 }
27254 }
27255
27256 // If any of the series have fixed color indexes, then we need to
27257 // generate at least as many colors as the highest index.
27258
27259 if (neededColors <= maxIndex) {
27260 neededColors = maxIndex + 1;
27261 }
27262
27263 // Generate all the colors, using first the option colors and then
27264 // variations on those colors once they're exhausted.
27265
27266 var c, colors = [], colorPool = options.colors,
27267 colorPoolSize = colorPool.length, variation = 0;
27268
27269 for (i = 0; i < neededColors; i++) {
27270
27271 c = $.color.parse(colorPool[i % colorPoolSize] || "#666");
27272
27273 // Each time we exhaust the colors in the pool we adjust
27274 // a scaling factor used to produce more variations on
27275 // those colors. The factor alternates negative/positive
27276 // to produce lighter/darker colors.
27277
27278 // Reset the variation after every few cycles, or else
27279 // it will end up producing only white or black colors.
27280
27281 if (i % colorPoolSize == 0 && i) {
27282 if (variation >= 0) {
27283 if (variation < 0.5) {
27284 variation = -variation - 0.2;
27285 } else variation = 0;
27286 } else variation = -variation;
27287 }
27288
27289 colors[i] = c.scale('rgb', 1 + variation);
27290 }
27291
27292 // Finalize the series options, filling in their colors
27293
27294 var colori = 0, s;
27295 for (i = 0; i < series.length; ++i) {
27296 s = series[i];
27297
27298 // assign colors
27299 if (s.color == null) {
27300 s.color = colors[colori].toString();
27301 ++colori;
27302 }
27303 else if (typeof s.color == "number")
27304 s.color = colors[s.color].toString();
27305
27306 // turn on lines automatically in case nothing is set
27307 if (s.lines.show == null) {
27308 var v, show = true;
27309 for (v in s)
27310 if (s[v] && s[v].show) {
27311 show = false;
27312 break;
27313 }
27314 if (show)
27315 s.lines.show = true;
27316 }
27317
27318 // If nothing was provided for lines.zero, default it to match
27319 // lines.fill, since areas by default should extend to zero.
27320
27321 if (s.lines.zero == null) {
27322 s.lines.zero = !!s.lines.fill;
27323 }
27324
27325 // setup axes
27326 s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
27327 s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
27328 }
27329 }
27330
27331 function processData() {
27332 var topSentry = Number.POSITIVE_INFINITY,
27333 bottomSentry = Number.NEGATIVE_INFINITY,
27334 fakeInfinity = Number.MAX_VALUE,
27335 i, j, k, m, length,
27336 s, points, ps, x, y, axis, val, f, p,
27337 data, format;
27338
27339 function updateAxis(axis, min, max) {
27340 if (min < axis.datamin && min != -fakeInfinity)
27341 axis.datamin = min;
27342 if (max > axis.datamax && max != fakeInfinity)
27343 axis.datamax = max;
27344 }
27345
27346 $.each(allAxes(), function (_, axis) {
27347 // init axis
27348 axis.datamin = topSentry;
27349 axis.datamax = bottomSentry;
27350 axis.used = false;
27351 });
27352
27353 for (i = 0; i < series.length; ++i) {
27354 s = series[i];
27355 s.datapoints = { points: [] };
27356
27357 executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
27358 }
27359
27360 // first pass: clean and copy data
27361 for (i = 0; i < series.length; ++i) {
27362 s = series[i];
27363
27364 data = s.data;
27365 format = s.datapoints.format;
27366
27367 if (!format) {
27368 format = [];
27369 // find out how to copy
27370 format.push({ x: true, number: true, required: true });
27371 format.push({ y: true, number: true, required: true });
27372
27373 if (s.bars.show || (s.lines.show && s.lines.fill)) {
27374 var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
27375 format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
27376 if (s.bars.horizontal) {
27377 delete format[format.length - 1].y;
27378 format[format.length - 1].x = true;
27379 }
27380 }
27381
27382 s.datapoints.format = format;
27383 }
27384
27385 if (s.datapoints.pointsize != null)
27386 continue; // already filled in
27387
27388 s.datapoints.pointsize = format.length;
27389
27390 ps = s.datapoints.pointsize;
27391 points = s.datapoints.points;
27392
27393 var insertSteps = s.lines.show && s.lines.steps;
27394 s.xaxis.used = s.yaxis.used = true;
27395
27396 for (j = k = 0; j < data.length; ++j, k += ps) {
27397 p = data[j];
27398
27399 var nullify = p == null;
27400 if (!nullify) {
27401 for (m = 0; m < ps; ++m) {
27402 val = p[m];
27403 f = format[m];
27404
27405 if (f) {
27406 if (f.number && val != null) {
27407 val = +val; // convert to number
27408 if (isNaN(val))
27409 val = null;
27410 else if (val == Infinity)
27411 val = fakeInfinity;
27412 else if (val == -Infinity)
27413 val = -fakeInfinity;
27414 }
27415
27416 if (val == null) {
27417 if (f.required)
27418 nullify = true;
27419
27420 if (f.defaultValue != null)
27421 val = f.defaultValue;
27422 }
27423 }
27424
27425 points[k + m] = val;
27426 }
27427 }
27428
27429 if (nullify) {
27430 for (m = 0; m < ps; ++m) {
27431 val = points[k + m];
27432 if (val != null) {
27433 f = format[m];
27434 // extract min/max info
27435 if (f.autoscale !== false) {
27436 if (f.x) {
27437 updateAxis(s.xaxis, val, val);
27438 }
27439 if (f.y) {
27440 updateAxis(s.yaxis, val, val);
27441 }
27442 }
27443 }
27444 points[k + m] = null;
27445 }
27446 }
27447 else {
27448 // a little bit of line specific stuff that
27449 // perhaps shouldn't be here, but lacking
27450 // better means...
27451 if (insertSteps && k > 0
27452 && points[k - ps] != null
27453 && points[k - ps] != points[k]
27454 && points[k - ps + 1] != points[k + 1]) {
27455 // copy the point to make room for a middle point
27456 for (m = 0; m < ps; ++m)
27457 points[k + ps + m] = points[k + m];
27458
27459 // middle point has same y
27460 points[k + 1] = points[k - ps + 1];
27461
27462 // we've added a point, better reflect that
27463 k += ps;
27464 }
27465 }
27466 }
27467 }
27468
27469 // give the hooks a chance to run
27470 for (i = 0; i < series.length; ++i) {
27471 s = series[i];
27472
27473 executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
27474 }
27475
27476 // second pass: find datamax/datamin for auto-scaling
27477 for (i = 0; i < series.length; ++i) {
27478 s = series[i];
27479 points = s.datapoints.points;
27480 ps = s.datapoints.pointsize;
27481 format = s.datapoints.format;
27482
27483 var xmin = topSentry, ymin = topSentry,
27484 xmax = bottomSentry, ymax = bottomSentry;
27485
27486 for (j = 0; j < points.length; j += ps) {
27487 if (points[j] == null)
27488 continue;
27489
27490 for (m = 0; m < ps; ++m) {
27491 val = points[j + m];
27492 f = format[m];
27493 if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity)
27494 continue;
27495
27496 if (f.x) {
27497 if (val < xmin)
27498 xmin = val;
27499 if (val > xmax)
27500 xmax = val;
27501 }
27502 if (f.y) {
27503 if (val < ymin)
27504 ymin = val;
27505 if (val > ymax)
27506 ymax = val;
27507 }
27508 }
27509 }
27510
27511 if (s.bars.show) {
27512 // make sure we got room for the bar on the dancing floor
27513 var delta;
27514
27515 switch (s.bars.align) {
27516 case "left":
27517 delta = 0;
27518 break;
27519 case "right":
27520 delta = -s.bars.barWidth;
27521 break;
27522 default:
27523 delta = -s.bars.barWidth / 2;
27524 }
27525
27526 if (s.bars.horizontal) {
27527 ymin += delta;
27528 ymax += delta + s.bars.barWidth;
27529 }
27530 else {
27531 xmin += delta;
27532 xmax += delta + s.bars.barWidth;
27533 }
27534 }
27535
27536 updateAxis(s.xaxis, xmin, xmax);
27537 updateAxis(s.yaxis, ymin, ymax);
27538 }
27539
27540 $.each(allAxes(), function (_, axis) {
27541 if (axis.datamin == topSentry)
27542 axis.datamin = null;
27543 if (axis.datamax == bottomSentry)
27544 axis.datamax = null;
27545 });
27546 }
27547
27548 function setupCanvases() {
27549
27550 // Make sure the placeholder is clear of everything except canvases
27551 // from a previous plot in this container that we'll try to re-use.
27552
27553 placeholder.css("padding", 0) // padding messes up the positioning
27554 .children().filter(function(){
27555 return !$(this).hasClass("flot-overlay") && !$(this).hasClass('flot-base');
27556 }).remove();
27557
27558 if (placeholder.css("position") == 'static')
27559 placeholder.css("position", "relative"); // for positioning labels and overlay
27560
27561 surface = new Canvas("flot-base", placeholder);
27562 overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features
27563
27564 ctx = surface.context;
27565 octx = overlay.context;
27566
27567 // define which element we're listening for events on
27568 eventHolder = $(overlay.element).unbind();
27569
27570 // If we're re-using a plot object, shut down the old one
27571
27572 var existing = placeholder.data("plot");
27573
27574 if (existing) {
27575 existing.shutdown();
27576 overlay.clear();
27577 }
27578
27579 // save in case we get replotted
27580 placeholder.data("plot", plot);
27581 }
27582
27583 function bindEvents() {
27584 // bind events
27585 if (options.grid.hoverable) {
27586 eventHolder.mousemove(onMouseMove);
27587
27588 // Use bind, rather than .mouseleave, because we officially
27589 // still support jQuery 1.2.6, which doesn't define a shortcut
27590 // for mouseenter or mouseleave. This was a bug/oversight that
27591 // was fixed somewhere around 1.3.x. We can return to using
27592 // .mouseleave when we drop support for 1.2.6.
27593
27594 eventHolder.bind("mouseleave", onMouseLeave);
27595 }
27596
27597 if (options.grid.clickable)
27598 eventHolder.click(onClick);
27599
27600 executeHooks(hooks.bindEvents, [eventHolder]);
27601 }
27602
27603 function shutdown() {
27604 if (redrawTimeout)
27605 clearTimeout(redrawTimeout);
27606
27607 eventHolder.unbind("mousemove", onMouseMove);
27608 eventHolder.unbind("mouseleave", onMouseLeave);
27609 eventHolder.unbind("click", onClick);
27610
27611 executeHooks(hooks.shutdown, [eventHolder]);
27612 }
27613
27614 function setTransformationHelpers(axis) {
27615 // set helper functions on the axis, assumes plot area
27616 // has been computed already
27617
27618 function identity(x) { return x; }
27619
27620 var s, m, t = axis.options.transform || identity,
27621 it = axis.options.inverseTransform;
27622
27623 // precompute how much the axis is scaling a point
27624 // in canvas space
27625 if (axis.direction == "x") {
27626 s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
27627 m = Math.min(t(axis.max), t(axis.min));
27628 }
27629 else {
27630 s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
27631 s = -s;
27632 m = Math.max(t(axis.max), t(axis.min));
27633 }
27634
27635 // data point to canvas coordinate
27636 if (t == identity) // slight optimization
27637 axis.p2c = function (p) { return (p - m) * s; };
27638 else
27639 axis.p2c = function (p) { return (t(p) - m) * s; };
27640 // canvas coordinate to data point
27641 if (!it)
27642 axis.c2p = function (c) { return m + c / s; };
27643 else
27644 axis.c2p = function (c) { return it(m + c / s); };
27645 }
27646
27647 function measureTickLabels(axis) {
27648
27649 var opts = axis.options,
27650 ticks = axis.ticks || [],
27651 labelWidth = opts.labelWidth || 0,
27652 labelHeight = opts.labelHeight || 0,
27653 maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null),
27654 legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
27655 layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
27656 font = opts.font || "flot-tick-label tickLabel";
27657
27658 for (var i = 0; i < ticks.length; ++i) {
27659
27660 var t = ticks[i];
27661
27662 if (!t.label)
27663 continue;
27664
27665 var info = surface.getTextInfo(layer, t.label, font, null, maxWidth);
27666
27667 labelWidth = Math.max(labelWidth, info.width);
27668 labelHeight = Math.max(labelHeight, info.height);
27669 }
27670
27671 axis.labelWidth = opts.labelWidth || labelWidth;
27672 axis.labelHeight = opts.labelHeight || labelHeight;
27673 }
27674
27675 function allocateAxisBoxFirstPhase(axis) {
27676 // find the bounding box of the axis by looking at label
27677 // widths/heights and ticks, make room by diminishing the
27678 // plotOffset; this first phase only looks at one
27679 // dimension per axis, the other dimension depends on the
27680 // other axes so will have to wait
27681
27682 var lw = axis.labelWidth,
27683 lh = axis.labelHeight,
27684 pos = axis.options.position,
27685 isXAxis = axis.direction === "x",
27686 tickLength = axis.options.tickLength,
27687 axisMargin = options.grid.axisMargin,
27688 padding = options.grid.labelMargin,
27689 innermost = true,
27690 outermost = true,
27691 first = true,
27692 found = false;
27693
27694 // Determine the axis's position in its direction and on its side
27695
27696 $.each(isXAxis ? xaxes : yaxes, function(i, a) {
27697 if (a && a.reserveSpace) {
27698 if (a === axis) {
27699 found = true;
27700 } else if (a.options.position === pos) {
27701 if (found) {
27702 outermost = false;
27703 } else {
27704 innermost = false;
27705 }
27706 }
27707 if (!found) {
27708 first = false;
27709 }
27710 }
27711 });
27712
27713 // The outermost axis on each side has no margin
27714
27715 if (outermost) {
27716 axisMargin = 0;
27717 }
27718
27719 // The ticks for the first axis in each direction stretch across
27720
27721 if (tickLength == null) {
27722 tickLength = first ? "full" : 5;
27723 }
27724
27725 if (!isNaN(+tickLength))
27726 padding += +tickLength;
27727
27728 if (isXAxis) {
27729 lh += padding;
27730
27731 if (pos == "bottom") {
27732 plotOffset.bottom += lh + axisMargin;
27733 axis.box = { top: surface.height - plotOffset.bottom, height: lh };
27734 }
27735 else {
27736 axis.box = { top: plotOffset.top + axisMargin, height: lh };
27737 plotOffset.top += lh + axisMargin;
27738 }
27739 }
27740 else {
27741 lw += padding;
27742
27743 if (pos == "left") {
27744 axis.box = { left: plotOffset.left + axisMargin, width: lw };
27745 plotOffset.left += lw + axisMargin;
27746 }
27747 else {
27748 plotOffset.right += lw + axisMargin;
27749 axis.box = { left: surface.width - plotOffset.right, width: lw };
27750 }
27751 }
27752
27753 // save for future reference
27754 axis.position = pos;
27755 axis.tickLength = tickLength;
27756 axis.box.padding = padding;
27757 axis.innermost = innermost;
27758 }
27759
27760 function allocateAxisBoxSecondPhase(axis) {
27761 // now that all axis boxes have been placed in one
27762 // dimension, we can set the remaining dimension coordinates
27763 if (axis.direction == "x") {
27764 axis.box.left = plotOffset.left - axis.labelWidth / 2;
27765 axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth;
27766 }
27767 else {
27768 axis.box.top = plotOffset.top - axis.labelHeight / 2;
27769 axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight;
27770 }
27771 }
27772
27773 function adjustLayoutForThingsStickingOut() {
27774 // possibly adjust plot offset to ensure everything stays
27775 // inside the canvas and isn't clipped off
27776
27777 var minMargin = options.grid.minBorderMargin,
27778 axis, i;
27779
27780 // check stuff from the plot (FIXME: this should just read
27781 // a value from the series, otherwise it's impossible to
27782 // customize)
27783 if (minMargin == null) {
27784 minMargin = 0;
27785 for (i = 0; i < series.length; ++i)
27786 minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
27787 }
27788
27789 var margins = {
27790 left: minMargin,
27791 right: minMargin,
27792 top: minMargin,
27793 bottom: minMargin
27794 };
27795
27796 // check axis labels, note we don't check the actual
27797 // labels but instead use the overall width/height to not
27798 // jump as much around with replots
27799 $.each(allAxes(), function (_, axis) {
27800 if (axis.reserveSpace && axis.ticks && axis.ticks.length) {
27801 var lastTick = axis.ticks[axis.ticks.length - 1];
27802 if (axis.direction === "x") {
27803 margins.left = Math.max(margins.left, axis.labelWidth / 2);
27804 if (lastTick.v <= axis.max) {
27805 margins.right = Math.max(margins.right, axis.labelWidth / 2);
27806 }
27807 } else {
27808 margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2);
27809 if (lastTick.v <= axis.max) {
27810 margins.top = Math.max(margins.top, axis.labelHeight / 2);
27811 }
27812 }
27813 }
27814 });
27815
27816 plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left));
27817 plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right));
27818 plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top));
27819 plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom));
27820 }
27821
27822 function setupGrid() {
27823 var i, axes = allAxes(), showGrid = options.grid.show;
27824
27825 // Initialize the plot's offset from the edge of the canvas
27826
27827 for (var a in plotOffset) {
27828 var margin = options.grid.margin || 0;
27829 plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0;
27830 }
27831
27832 executeHooks(hooks.processOffset, [plotOffset]);
27833
27834 // If the grid is visible, add its border width to the offset
27835
27836 for (var a in plotOffset) {
27837 if(typeof(options.grid.borderWidth) == "object") {
27838 plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0;
27839 }
27840 else {
27841 plotOffset[a] += showGrid ? options.grid.borderWidth : 0;
27842 }
27843 }
27844
27845 // init axes
27846 $.each(axes, function (_, axis) {
27847 axis.show = axis.options.show;
27848 if (axis.show == null)
27849 axis.show = axis.used; // by default an axis is visible if it's got data
27850
27851 axis.reserveSpace = axis.show || axis.options.reserveSpace;
27852
27853 setRange(axis);
27854 });
27855
27856 if (showGrid) {
27857
27858 var allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });
27859
27860 $.each(allocatedAxes, function (_, axis) {
27861 // make the ticks
27862 setupTickGeneration(axis);
27863 setTicks(axis);
27864 snapRangeToTicks(axis, axis.ticks);
27865 // find labelWidth/Height for axis
27866 measureTickLabels(axis);
27867 });
27868
27869 // with all dimensions calculated, we can compute the
27870 // axis bounding boxes, start from the outside
27871 // (reverse order)
27872 for (i = allocatedAxes.length - 1; i >= 0; --i)
27873 allocateAxisBoxFirstPhase(allocatedAxes[i]);
27874
27875 // make sure we've got enough space for things that
27876 // might stick out
27877 adjustLayoutForThingsStickingOut();
27878
27879 $.each(allocatedAxes, function (_, axis) {
27880 allocateAxisBoxSecondPhase(axis);
27881 });
27882 }
27883
27884 plotWidth = surface.width - plotOffset.left - plotOffset.right;
27885 plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
27886
27887 // now we got the proper plot dimensions, we can compute the scaling
27888 $.each(axes, function (_, axis) {
27889 setTransformationHelpers(axis);
27890 });
27891
27892 if (showGrid) {
27893 drawAxisLabels();
27894 }
27895
27896 insertLegend();
27897 }
27898
27899 function setRange(axis) {
27900 var opts = axis.options,
27901 min = +(opts.min != null ? opts.min : axis.datamin),
27902 max = +(opts.max != null ? opts.max : axis.datamax),
27903 delta = max - min;
27904
27905 if (delta == 0.0) {
27906 // degenerate case
27907 var widen = max == 0 ? 1 : 0.01;
27908
27909 if (opts.min == null)
27910 min -= widen;
27911 // always widen max if we couldn't widen min to ensure we
27912 // don't fall into min == max which doesn't work
27913 if (opts.max == null || opts.min != null)
27914 max += widen;
27915 }
27916 else {
27917 // consider autoscaling
27918 var margin = opts.autoscaleMargin;
27919 if (margin != null) {
27920 if (opts.min == null) {
27921 min -= delta * margin;
27922 // make sure we don't go below zero if all values
27923 // are positive
27924 if (min < 0 && axis.datamin != null && axis.datamin >= 0)
27925 min = 0;
27926 }
27927 if (opts.max == null) {
27928 max += delta * margin;
27929 if (max > 0 && axis.datamax != null && axis.datamax <= 0)
27930 max = 0;
27931 }
27932 }
27933 }
27934 axis.min = min;
27935 axis.max = max;
27936 }
27937
27938 function setupTickGeneration(axis) {
27939 var opts = axis.options;
27940
27941 // estimate number of ticks
27942 var noTicks;
27943 if (typeof opts.ticks == "number" && opts.ticks > 0)
27944 noTicks = opts.ticks;
27945 else
27946 // heuristic based on the model a*sqrt(x) fitted to
27947 // some data points that seemed reasonable
27948 noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? surface.width : surface.height);
27949
27950 var delta = (axis.max - axis.min) / noTicks,
27951 dec = -Math.floor(Math.log(delta) / Math.LN10),
27952 maxDec = opts.tickDecimals;
27953
27954 if (maxDec != null && dec > maxDec) {
27955 dec = maxDec;
27956 }
27957
27958 var magn = Math.pow(10, -dec),
27959 norm = delta / magn, // norm is between 1.0 and 10.0
27960 size;
27961
27962 if (norm < 1.5) {
27963 size = 1;
27964 } else if (norm < 3) {
27965 size = 2;
27966 // special case for 2.5, requires an extra decimal
27967 if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
27968 size = 2.5;
27969 ++dec;
27970 }
27971 } else if (norm < 7.5) {
27972 size = 5;
27973 } else {
27974 size = 10;
27975 }
27976
27977 size *= magn;
27978
27979 if (opts.minTickSize != null && size < opts.minTickSize) {
27980 size = opts.minTickSize;
27981 }
27982
27983 axis.delta = delta;
27984 axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
27985 axis.tickSize = opts.tickSize || size;
27986
27987 // Time mode was moved to a plug-in in 0.8, and since so many people use it
27988 // we'll add an especially friendly reminder to make sure they included it.
27989
27990 if (opts.mode == "time" && !axis.tickGenerator) {
27991 throw new Error("Time mode requires the flot.time plugin.");
27992 }
27993
27994 // Flot supports base-10 axes; any other mode else is handled by a plug-in,
27995 // like flot.time.js.
27996
27997 if (!axis.tickGenerator) {
27998
27999 axis.tickGenerator = function (axis) {
28000
28001 var ticks = [],
28002 start = floorInBase(axis.min, axis.tickSize),
28003 i = 0,
28004 v = Number.NaN,
28005 prev;
28006
28007 do {
28008 prev = v;
28009 v = start + i * axis.tickSize;
28010 ticks.push(v);
28011 ++i;
28012 } while (v < axis.max && v != prev);
28013 return ticks;
28014 };
28015
28016 axis.tickFormatter = function (value, axis) {
28017
28018 var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1;
28019 var formatted = "" + Math.round(value * factor) / factor;
28020
28021 // If tickDecimals was specified, ensure that we have exactly that
28022 // much precision; otherwise default to the value's own precision.
28023
28024 if (axis.tickDecimals != null) {
28025 var decimal = formatted.indexOf(".");
28026 var precision = decimal == -1 ? 0 : formatted.length - decimal - 1;
28027 if (precision < axis.tickDecimals) {
28028 return (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);
28029 }
28030 }
28031
28032 return formatted;
28033 };
28034 }
28035
28036 if ($.isFunction(opts.tickFormatter))
28037 axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
28038
28039 if (opts.alignTicksWithAxis != null) {
28040 var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
28041 if (otherAxis && otherAxis.used && otherAxis != axis) {
28042 // consider snapping min/max to outermost nice ticks
28043 var niceTicks = axis.tickGenerator(axis);
28044 if (niceTicks.length > 0) {
28045 if (opts.min == null)
28046 axis.min = Math.min(axis.min, niceTicks[0]);
28047 if (opts.max == null && niceTicks.length > 1)
28048 axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
28049 }
28050
28051 axis.tickGenerator = function (axis) {
28052 // copy ticks, scaled to this axis
28053 var ticks = [], v, i;
28054 for (i = 0; i < otherAxis.ticks.length; ++i) {
28055 v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
28056 v = axis.min + v * (axis.max - axis.min);
28057 ticks.push(v);
28058 }
28059 return ticks;
28060 };
28061
28062 // we might need an extra decimal since forced
28063 // ticks don't necessarily fit naturally
28064 if (!axis.mode && opts.tickDecimals == null) {
28065 var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
28066 ts = axis.tickGenerator(axis);
28067
28068 // only proceed if the tick interval rounded
28069 // with an extra decimal doesn't give us a
28070 // zero at end
28071 if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
28072 axis.tickDecimals = extraDec;
28073 }
28074 }
28075 }
28076 }
28077
28078 function setTicks(axis) {
28079 var oticks = axis.options.ticks, ticks = [];
28080 if (oticks == null || (typeof oticks == "number" && oticks > 0))
28081 ticks = axis.tickGenerator(axis);
28082 else if (oticks) {
28083 if ($.isFunction(oticks))
28084 // generate the ticks
28085 ticks = oticks(axis);
28086 else
28087 ticks = oticks;
28088 }
28089
28090 // clean up/labelify the supplied ticks, copy them over
28091 var i, v;
28092 axis.ticks = [];
28093 for (i = 0; i < ticks.length; ++i) {
28094 var label = null;
28095 var t = ticks[i];
28096 if (typeof t == "object") {
28097 v = +t[0];
28098 if (t.length > 1)
28099 label = t[1];
28100 }
28101 else
28102 v = +t;
28103 if (label == null)
28104 label = axis.tickFormatter(v, axis);
28105 if (!isNaN(v))
28106 axis.ticks.push({ v: v, label: label });
28107 }
28108 }
28109
28110 function snapRangeToTicks(axis, ticks) {
28111 if (axis.options.autoscaleMargin && ticks.length > 0) {
28112 // snap to ticks
28113 if (axis.options.min == null)
28114 axis.min = Math.min(axis.min, ticks[0].v);
28115 if (axis.options.max == null && ticks.length > 1)
28116 axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
28117 }
28118 }
28119
28120 function draw() {
28121
28122 surface.clear();
28123
28124 executeHooks(hooks.drawBackground, [ctx]);
28125
28126 var grid = options.grid;
28127
28128 // draw background, if any
28129 if (grid.show && grid.backgroundColor)
28130 drawBackground();
28131
28132 if (grid.show && !grid.aboveData) {
28133 drawGrid();
28134 }
28135
28136 for (var i = 0; i < series.length; ++i) {
28137 executeHooks(hooks.drawSeries, [ctx, series[i]]);
28138 drawSeries(series[i]);
28139 }
28140
28141 executeHooks(hooks.draw, [ctx]);
28142
28143 if (grid.show && grid.aboveData) {
28144 drawGrid();
28145 }
28146
28147 surface.render();
28148
28149 // A draw implies that either the axes or data have changed, so we
28150 // should probably update the overlay highlights as well.
28151
28152 triggerRedrawOverlay();
28153 }
28154
28155 function extractRange(ranges, coord) {
28156 var axis, from, to, key, axes = allAxes();
28157
28158 for (var i = 0; i < axes.length; ++i) {
28159 axis = axes[i];
28160 if (axis.direction == coord) {
28161 key = coord + axis.n + "axis";
28162 if (!ranges[key] && axis.n == 1)
28163 key = coord + "axis"; // support x1axis as xaxis
28164 if (ranges[key]) {
28165 from = ranges[key].from;
28166 to = ranges[key].to;
28167 break;
28168 }
28169 }
28170 }
28171
28172 // backwards-compat stuff - to be removed in future
28173 if (!ranges[key]) {
28174 axis = coord == "x" ? xaxes[0] : yaxes[0];
28175 from = ranges[coord + "1"];
28176 to = ranges[coord + "2"];
28177 }
28178
28179 // auto-reverse as an added bonus
28180 if (from != null && to != null && from > to) {
28181 var tmp = from;
28182 from = to;
28183 to = tmp;
28184 }
28185
28186 return { from: from, to: to, axis: axis };
28187 }
28188
28189 function drawBackground() {
28190 ctx.save();
28191 ctx.translate(plotOffset.left, plotOffset.top);
28192
28193 ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
28194 ctx.fillRect(0, 0, plotWidth, plotHeight);
28195 ctx.restore();
28196 }
28197
28198 function drawGrid() {
28199 var i, axes, bw, bc;
28200
28201 ctx.save();
28202 ctx.translate(plotOffset.left, plotOffset.top);
28203
28204 // draw markings
28205 var markings = options.grid.markings;
28206 if (markings) {
28207 if ($.isFunction(markings)) {
28208 axes = plot.getAxes();
28209 // xmin etc. is backwards compatibility, to be
28210 // removed in the future
28211 axes.xmin = axes.xaxis.min;
28212 axes.xmax = axes.xaxis.max;
28213 axes.ymin = axes.yaxis.min;
28214 axes.ymax = axes.yaxis.max;
28215
28216 markings = markings(axes);
28217 }
28218
28219 for (i = 0; i < markings.length; ++i) {
28220 var m = markings[i],
28221 xrange = extractRange(m, "x"),
28222 yrange = extractRange(m, "y");
28223
28224 // fill in missing
28225 if (xrange.from == null)
28226 xrange.from = xrange.axis.min;
28227 if (xrange.to == null)
28228 xrange.to = xrange.axis.max;
28229 if (yrange.from == null)
28230 yrange.from = yrange.axis.min;
28231 if (yrange.to == null)
28232 yrange.to = yrange.axis.max;
28233
28234 // clip
28235 if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
28236 yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
28237 continue;
28238
28239 xrange.from = Math.max(xrange.from, xrange.axis.min);
28240 xrange.to = Math.min(xrange.to, xrange.axis.max);
28241 yrange.from = Math.max(yrange.from, yrange.axis.min);
28242 yrange.to = Math.min(yrange.to, yrange.axis.max);
28243
28244 var xequal = xrange.from === xrange.to,
28245 yequal = yrange.from === yrange.to;
28246
28247 if (xequal && yequal) {
28248 continue;
28249 }
28250
28251 // then draw
28252 xrange.from = Math.floor(xrange.axis.p2c(xrange.from));
28253 xrange.to = Math.floor(xrange.axis.p2c(xrange.to));
28254 yrange.from = Math.floor(yrange.axis.p2c(yrange.from));
28255 yrange.to = Math.floor(yrange.axis.p2c(yrange.to));
28256
28257 if (xequal || yequal) {
28258 var lineWidth = m.lineWidth || options.grid.markingsLineWidth,
28259 subPixel = lineWidth % 2 ? 0.5 : 0;
28260 ctx.beginPath();
28261 ctx.strokeStyle = m.color || options.grid.markingsColor;
28262 ctx.lineWidth = lineWidth;
28263 if (xequal) {
28264 ctx.moveTo(xrange.to + subPixel, yrange.from);
28265 ctx.lineTo(xrange.to + subPixel, yrange.to);
28266 } else {
28267 ctx.moveTo(xrange.from, yrange.to + subPixel);
28268 ctx.lineTo(xrange.to, yrange.to + subPixel);
28269 }
28270 ctx.stroke();
28271 } else {
28272 ctx.fillStyle = m.color || options.grid.markingsColor;
28273 ctx.fillRect(xrange.from, yrange.to,
28274 xrange.to - xrange.from,
28275 yrange.from - yrange.to);
28276 }
28277 }
28278 }
28279
28280 // draw the ticks
28281 axes = allAxes();
28282 bw = options.grid.borderWidth;
28283
28284 for (var j = 0; j < axes.length; ++j) {
28285 var axis = axes[j], box = axis.box,
28286 t = axis.tickLength, x, y, xoff, yoff;
28287 if (!axis.show || axis.ticks.length == 0)
28288 continue;
28289
28290 ctx.lineWidth = 1;
28291
28292 // find the edges
28293 if (axis.direction == "x") {
28294 x = 0;
28295 if (t == "full")
28296 y = (axis.position == "top" ? 0 : plotHeight);
28297 else
28298 y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
28299 }
28300 else {
28301 y = 0;
28302 if (t == "full")
28303 x = (axis.position == "left" ? 0 : plotWidth);
28304 else
28305 x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
28306 }
28307
28308 // draw tick bar
28309 if (!axis.innermost) {
28310 ctx.strokeStyle = axis.options.color;
28311 ctx.beginPath();
28312 xoff = yoff = 0;
28313 if (axis.direction == "x")
28314 xoff = plotWidth + 1;
28315 else
28316 yoff = plotHeight + 1;
28317
28318 if (ctx.lineWidth == 1) {
28319 if (axis.direction == "x") {
28320 y = Math.floor(y) + 0.5;
28321 } else {
28322 x = Math.floor(x) + 0.5;
28323 }
28324 }
28325
28326 ctx.moveTo(x, y);
28327 ctx.lineTo(x + xoff, y + yoff);
28328 ctx.stroke();
28329 }
28330
28331 // draw ticks
28332
28333 ctx.strokeStyle = axis.options.tickColor;
28334
28335 ctx.beginPath();
28336 for (i = 0; i < axis.ticks.length; ++i) {
28337 var v = axis.ticks[i].v;
28338
28339 xoff = yoff = 0;
28340
28341 if (isNaN(v) || v < axis.min || v > axis.max
28342 // skip those lying on the axes if we got a border
28343 || (t == "full"
28344 && ((typeof bw == "object" && bw[axis.position] > 0) || bw > 0)
28345 && (v == axis.min || v == axis.max)))
28346 continue;
28347
28348 if (axis.direction == "x") {
28349 x = axis.p2c(v);
28350 yoff = t == "full" ? -plotHeight : t;
28351
28352 if (axis.position == "top")
28353 yoff = -yoff;
28354 }
28355 else {
28356 y = axis.p2c(v);
28357 xoff = t == "full" ? -plotWidth : t;
28358
28359 if (axis.position == "left")
28360 xoff = -xoff;
28361 }
28362
28363 if (ctx.lineWidth == 1) {
28364 if (axis.direction == "x")
28365 x = Math.floor(x) + 0.5;
28366 else
28367 y = Math.floor(y) + 0.5;
28368 }
28369
28370 ctx.moveTo(x, y);
28371 ctx.lineTo(x + xoff, y + yoff);
28372 }
28373
28374 ctx.stroke();
28375 }
28376
28377
28378 // draw border
28379 if (bw) {
28380 // If either borderWidth or borderColor is an object, then draw the border
28381 // line by line instead of as one rectangle
28382 bc = options.grid.borderColor;
28383 if(typeof bw == "object" || typeof bc == "object") {
28384 if (typeof bw !== "object") {
28385 bw = {top: bw, right: bw, bottom: bw, left: bw};
28386 }
28387 if (typeof bc !== "object") {
28388 bc = {top: bc, right: bc, bottom: bc, left: bc};
28389 }
28390
28391 if (bw.top > 0) {
28392 ctx.strokeStyle = bc.top;
28393 ctx.lineWidth = bw.top;
28394 ctx.beginPath();
28395 ctx.moveTo(0 - bw.left, 0 - bw.top/2);
28396 ctx.lineTo(plotWidth, 0 - bw.top/2);
28397 ctx.stroke();
28398 }
28399
28400 if (bw.right > 0) {
28401 ctx.strokeStyle = bc.right;
28402 ctx.lineWidth = bw.right;
28403 ctx.beginPath();
28404 ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top);
28405 ctx.lineTo(plotWidth + bw.right / 2, plotHeight);
28406 ctx.stroke();
28407 }
28408
28409 if (bw.bottom > 0) {
28410 ctx.strokeStyle = bc.bottom;
28411 ctx.lineWidth = bw.bottom;
28412 ctx.beginPath();
28413 ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2);
28414 ctx.lineTo(0, plotHeight + bw.bottom / 2);
28415 ctx.stroke();
28416 }
28417
28418 if (bw.left > 0) {
28419 ctx.strokeStyle = bc.left;
28420 ctx.lineWidth = bw.left;
28421 ctx.beginPath();
28422 ctx.moveTo(0 - bw.left/2, plotHeight + bw.bottom);
28423 ctx.lineTo(0- bw.left/2, 0);
28424 ctx.stroke();
28425 }
28426 }
28427 else {
28428 ctx.lineWidth = bw;
28429 ctx.strokeStyle = options.grid.borderColor;
28430 ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
28431 }
28432 }
28433
28434 ctx.restore();
28435 }
28436
28437 function drawAxisLabels() {
28438
28439 $.each(allAxes(), function (_, axis) {
28440 var box = axis.box,
28441 legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
28442 layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
28443 font = axis.options.font || "flot-tick-label tickLabel",
28444 tick, x, y, halign, valign;
28445
28446 // Remove text before checking for axis.show and ticks.length;
28447 // otherwise plugins, like flot-tickrotor, that draw their own
28448 // tick labels will end up with both theirs and the defaults.
28449
28450 surface.removeText(layer);
28451
28452 if (!axis.show || axis.ticks.length == 0)
28453 return;
28454
28455 for (var i = 0; i < axis.ticks.length; ++i) {
28456
28457 tick = axis.ticks[i];
28458 if (!tick.label || tick.v < axis.min || tick.v > axis.max)
28459 continue;
28460
28461 if (axis.direction == "x") {
28462 halign = "center";
28463 x = plotOffset.left + axis.p2c(tick.v);
28464 if (axis.position == "bottom") {
28465 y = box.top + box.padding;
28466 } else {
28467 y = box.top + box.height - box.padding;
28468 valign = "bottom";
28469 }
28470 } else {
28471 valign = "middle";
28472 y = plotOffset.top + axis.p2c(tick.v);
28473 if (axis.position == "left") {
28474 x = box.left + box.width - box.padding;
28475 halign = "right";
28476 } else {
28477 x = box.left + box.padding;
28478 }
28479 }
28480
28481 surface.addText(layer, x, y, tick.label, font, null, null, halign, valign);
28482 }
28483 });
28484 }
28485
28486 function drawSeries(series) {
28487 if (series.lines.show)
28488 drawSeriesLines(series);
28489 if (series.bars.show)
28490 drawSeriesBars(series);
28491 if (series.points.show)
28492 drawSeriesPoints(series);
28493 }
28494
28495 function drawSeriesLines(series) {
28496 function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
28497 var points = datapoints.points,
28498 ps = datapoints.pointsize,
28499 prevx = null, prevy = null;
28500
28501 ctx.beginPath();
28502 for (var i = ps; i < points.length; i += ps) {
28503 var x1 = points[i - ps], y1 = points[i - ps + 1],
28504 x2 = points[i], y2 = points[i + 1];
28505
28506 if (x1 == null || x2 == null)
28507 continue;
28508
28509 // clip with ymin
28510 if (y1 <= y2 && y1 < axisy.min) {
28511 if (y2 < axisy.min)
28512 continue; // line segment is outside
28513 // compute new intersection point
28514 x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
28515 y1 = axisy.min;
28516 }
28517 else if (y2 <= y1 && y2 < axisy.min) {
28518 if (y1 < axisy.min)
28519 continue;
28520 x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
28521 y2 = axisy.min;
28522 }
28523
28524 // clip with ymax
28525 if (y1 >= y2 && y1 > axisy.max) {
28526 if (y2 > axisy.max)
28527 continue;
28528 x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
28529 y1 = axisy.max;
28530 }
28531 else if (y2 >= y1 && y2 > axisy.max) {
28532 if (y1 > axisy.max)
28533 continue;
28534 x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
28535 y2 = axisy.max;
28536 }
28537
28538 // clip with xmin
28539 if (x1 <= x2 && x1 < axisx.min) {
28540 if (x2 < axisx.min)
28541 continue;
28542 y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
28543 x1 = axisx.min;
28544 }
28545 else if (x2 <= x1 && x2 < axisx.min) {
28546 if (x1 < axisx.min)
28547 continue;
28548 y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
28549 x2 = axisx.min;
28550 }
28551
28552 // clip with xmax
28553 if (x1 >= x2 && x1 > axisx.max) {
28554 if (x2 > axisx.max)
28555 continue;
28556 y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
28557 x1 = axisx.max;
28558 }
28559 else if (x2 >= x1 && x2 > axisx.max) {
28560 if (x1 > axisx.max)
28561 continue;
28562 y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
28563 x2 = axisx.max;
28564 }
28565
28566 if (x1 != prevx || y1 != prevy)
28567 ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
28568
28569 prevx = x2;
28570 prevy = y2;
28571 ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
28572 }
28573 ctx.stroke();
28574 }
28575
28576 function plotLineArea(datapoints, axisx, axisy) {
28577 var points = datapoints.points,
28578 ps = datapoints.pointsize,
28579 bottom = Math.min(Math.max(0, axisy.min), axisy.max),
28580 i = 0, top, areaOpen = false,
28581 ypos = 1, segmentStart = 0, segmentEnd = 0;
28582
28583 // we process each segment in two turns, first forward
28584 // direction to sketch out top, then once we hit the
28585 // end we go backwards to sketch the bottom
28586 while (true) {
28587 if (ps > 0 && i > points.length + ps)
28588 break;
28589
28590 i += ps; // ps is negative if going backwards
28591
28592 var x1 = points[i - ps],
28593 y1 = points[i - ps + ypos],
28594 x2 = points[i], y2 = points[i + ypos];
28595
28596 if (areaOpen) {
28597 if (ps > 0 && x1 != null && x2 == null) {
28598 // at turning point
28599 segmentEnd = i;
28600 ps = -ps;
28601 ypos = 2;
28602 continue;
28603 }
28604
28605 if (ps < 0 && i == segmentStart + ps) {
28606 // done with the reverse sweep
28607 ctx.fill();
28608 areaOpen = false;
28609 ps = -ps;
28610 ypos = 1;
28611 i = segmentStart = segmentEnd + ps;
28612 continue;
28613 }
28614 }
28615
28616 if (x1 == null || x2 == null)
28617 continue;
28618
28619 // clip x values
28620
28621 // clip with xmin
28622 if (x1 <= x2 && x1 < axisx.min) {
28623 if (x2 < axisx.min)
28624 continue;
28625 y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
28626 x1 = axisx.min;
28627 }
28628 else if (x2 <= x1 && x2 < axisx.min) {
28629 if (x1 < axisx.min)
28630 continue;
28631 y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
28632 x2 = axisx.min;
28633 }
28634
28635 // clip with xmax
28636 if (x1 >= x2 && x1 > axisx.max) {
28637 if (x2 > axisx.max)
28638 continue;
28639 y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
28640 x1 = axisx.max;
28641 }
28642 else if (x2 >= x1 && x2 > axisx.max) {
28643 if (x1 > axisx.max)
28644 continue;
28645 y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
28646 x2 = axisx.max;
28647 }
28648
28649 if (!areaOpen) {
28650 // open area
28651 ctx.beginPath();
28652 ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
28653 areaOpen = true;
28654 }
28655
28656 // now first check the case where both is outside
28657 if (y1 >= axisy.max && y2 >= axisy.max) {
28658 ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
28659 ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
28660 continue;
28661 }
28662 else if (y1 <= axisy.min && y2 <= axisy.min) {
28663 ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
28664 ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
28665 continue;
28666 }
28667
28668 // else it's a bit more complicated, there might
28669 // be a flat maxed out rectangle first, then a
28670 // triangular cutout or reverse; to find these
28671 // keep track of the current x values
28672 var x1old = x1, x2old = x2;
28673
28674 // clip the y values, without shortcutting, we
28675 // go through all cases in turn
28676
28677 // clip with ymin
28678 if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
28679 x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
28680 y1 = axisy.min;
28681 }
28682 else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
28683 x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
28684 y2 = axisy.min;
28685 }
28686
28687 // clip with ymax
28688 if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
28689 x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
28690 y1 = axisy.max;
28691 }
28692 else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
28693 x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
28694 y2 = axisy.max;
28695 }
28696
28697 // if the x value was changed we got a rectangle
28698 // to fill
28699 if (x1 != x1old) {
28700 ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
28701 // it goes to (x1, y1), but we fill that below
28702 }
28703
28704 // fill triangular section, this sometimes result
28705 // in redundant points if (x1, y1) hasn't changed
28706 // from previous line to, but we just ignore that
28707 ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
28708 ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
28709
28710 // fill the other rectangle if it's there
28711 if (x2 != x2old) {
28712 ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
28713 ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
28714 }
28715 }
28716 }
28717
28718 ctx.save();
28719 ctx.translate(plotOffset.left, plotOffset.top);
28720 ctx.lineJoin = "round";
28721
28722 var lw = series.lines.lineWidth,
28723 sw = series.shadowSize;
28724 // FIXME: consider another form of shadow when filling is turned on
28725 if (lw > 0 && sw > 0) {
28726 // draw shadow as a thick and thin line with transparency
28727 ctx.lineWidth = sw;
28728 ctx.strokeStyle = "rgba(0,0,0,0.1)";
28729 // position shadow at angle from the mid of line
28730 var angle = Math.PI/18;
28731 plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
28732 ctx.lineWidth = sw/2;
28733 plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
28734 }
28735
28736 ctx.lineWidth = lw;
28737 ctx.strokeStyle = series.color;
28738 var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
28739 if (fillStyle) {
28740 ctx.fillStyle = fillStyle;
28741 plotLineArea(series.datapoints, series.xaxis, series.yaxis);
28742 }
28743
28744 if (lw > 0)
28745 plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
28746 ctx.restore();
28747 }
28748
28749 function drawSeriesPoints(series) {
28750 function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
28751 var points = datapoints.points, ps = datapoints.pointsize;
28752
28753 for (var i = 0; i < points.length; i += ps) {
28754 var x = points[i], y = points[i + 1];
28755 if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
28756 continue;
28757
28758 ctx.beginPath();
28759 x = axisx.p2c(x);
28760 y = axisy.p2c(y) + offset;
28761 if (symbol == "circle")
28762 ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
28763 else
28764 symbol(ctx, x, y, radius, shadow);
28765 ctx.closePath();
28766
28767 if (fillStyle) {
28768 ctx.fillStyle = fillStyle;
28769 ctx.fill();
28770 }
28771 ctx.stroke();
28772 }
28773 }
28774
28775 ctx.save();
28776 ctx.translate(plotOffset.left, plotOffset.top);
28777
28778 var lw = series.points.lineWidth,
28779 sw = series.shadowSize,
28780 radius = series.points.radius,
28781 symbol = series.points.symbol;
28782
28783 // If the user sets the line width to 0, we change it to a very
28784 // small value. A line width of 0 seems to force the default of 1.
28785 // Doing the conditional here allows the shadow setting to still be
28786 // optional even with a lineWidth of 0.
28787
28788 if( lw == 0 )
28789 lw = 0.0001;
28790
28791 if (lw > 0 && sw > 0) {
28792 // draw shadow in two steps
28793 var w = sw / 2;
28794 ctx.lineWidth = w;
28795 ctx.strokeStyle = "rgba(0,0,0,0.1)";
28796 plotPoints(series.datapoints, radius, null, w + w/2, true,
28797 series.xaxis, series.yaxis, symbol);
28798
28799 ctx.strokeStyle = "rgba(0,0,0,0.2)";
28800 plotPoints(series.datapoints, radius, null, w/2, true,
28801 series.xaxis, series.yaxis, symbol);
28802 }
28803
28804 ctx.lineWidth = lw;
28805 ctx.strokeStyle = series.color;
28806 plotPoints(series.datapoints, radius,
28807 getFillStyle(series.points, series.color), 0, false,
28808 series.xaxis, series.yaxis, symbol);
28809 ctx.restore();
28810 }
28811
28812 function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
28813 var left, right, bottom, top,
28814 drawLeft, drawRight, drawTop, drawBottom,
28815 tmp;
28816
28817 // in horizontal mode, we start the bar from the left
28818 // instead of from the bottom so it appears to be
28819 // horizontal rather than vertical
28820 if (horizontal) {
28821 drawBottom = drawRight = drawTop = true;
28822 drawLeft = false;
28823 left = b;
28824 right = x;
28825 top = y + barLeft;
28826 bottom = y + barRight;
28827
28828 // account for negative bars
28829 if (right < left) {
28830 tmp = right;
28831 right = left;
28832 left = tmp;
28833 drawLeft = true;
28834 drawRight = false;
28835 }
28836 }
28837 else {
28838 drawLeft = drawRight = drawTop = true;
28839 drawBottom = false;
28840 left = x + barLeft;
28841 right = x + barRight;
28842 bottom = b;
28843 top = y;
28844
28845 // account for negative bars
28846 if (top < bottom) {
28847 tmp = top;
28848 top = bottom;
28849 bottom = tmp;
28850 drawBottom = true;
28851 drawTop = false;
28852 }
28853 }
28854
28855 // clip
28856 if (right < axisx.min || left > axisx.max ||
28857 top < axisy.min || bottom > axisy.max)
28858 return;
28859
28860 if (left < axisx.min) {
28861 left = axisx.min;
28862 drawLeft = false;
28863 }
28864
28865 if (right > axisx.max) {
28866 right = axisx.max;
28867 drawRight = false;
28868 }
28869
28870 if (bottom < axisy.min) {
28871 bottom = axisy.min;
28872 drawBottom = false;
28873 }
28874
28875 if (top > axisy.max) {
28876 top = axisy.max;
28877 drawTop = false;
28878 }
28879
28880 left = axisx.p2c(left);
28881 bottom = axisy.p2c(bottom);
28882 right = axisx.p2c(right);
28883 top = axisy.p2c(top);
28884
28885 // fill the bar
28886 if (fillStyleCallback) {
28887 c.fillStyle = fillStyleCallback(bottom, top);
28888 c.fillRect(left, top, right - left, bottom - top)
28889 }
28890
28891 // draw outline
28892 if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
28893 c.beginPath();
28894
28895 // FIXME: inline moveTo is buggy with excanvas
28896 c.moveTo(left, bottom);
28897 if (drawLeft)
28898 c.lineTo(left, top);
28899 else
28900 c.moveTo(left, top);
28901 if (drawTop)
28902 c.lineTo(right, top);
28903 else
28904 c.moveTo(right, top);
28905 if (drawRight)
28906 c.lineTo(right, bottom);
28907 else
28908 c.moveTo(right, bottom);
28909 if (drawBottom)
28910 c.lineTo(left, bottom);
28911 else
28912 c.moveTo(left, bottom);
28913 c.stroke();
28914 }
28915 }
28916
28917 function drawSeriesBars(series) {
28918 function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {
28919 var points = datapoints.points, ps = datapoints.pointsize;
28920
28921 for (var i = 0; i < points.length; i += ps) {
28922 if (points[i] == null)
28923 continue;
28924 drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
28925 }
28926 }
28927
28928 ctx.save();
28929 ctx.translate(plotOffset.left, plotOffset.top);
28930
28931 // FIXME: figure out a way to add shadows (for instance along the right edge)
28932 ctx.lineWidth = series.bars.lineWidth;
28933 ctx.strokeStyle = series.color;
28934
28935 var barLeft;
28936
28937 switch (series.bars.align) {
28938 case "left":
28939 barLeft = 0;
28940 break;
28941 case "right":
28942 barLeft = -series.bars.barWidth;
28943 break;
28944 default:
28945 barLeft = -series.bars.barWidth / 2;
28946 }
28947
28948 var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
28949 plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis);
28950 ctx.restore();
28951 }
28952
28953 function getFillStyle(filloptions, seriesColor, bottom, top) {
28954 var fill = filloptions.fill;
28955 if (!fill)
28956 return null;
28957
28958 if (filloptions.fillColor)
28959 return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
28960
28961 var c = $.color.parse(seriesColor);
28962 c.a = typeof fill == "number" ? fill : 0.4;
28963 c.normalize();
28964 return c.toString();
28965 }
28966
28967 function insertLegend() {
28968
28969 if (options.legend.container != null) {
28970 $(options.legend.container).html("");
28971 } else {
28972 placeholder.find(".legend").remove();
28973 }
28974
28975 if (!options.legend.show) {
28976 return;
28977 }
28978
28979 var fragments = [], entries = [], rowStarted = false,
28980 lf = options.legend.labelFormatter, s, label;
28981
28982 // Build a list of legend entries, with each having a label and a color
28983
28984 for (var i = 0; i < series.length; ++i) {
28985 s = series[i];
28986 if (s.label) {
28987 label = lf ? lf(s.label, s) : s.label;
28988 if (label) {
28989 entries.push({
28990 label: label,
28991 color: s.color
28992 });
28993 }
28994 }
28995 }
28996
28997 // Sort the legend using either the default or a custom comparator
28998
28999 if (options.legend.sorted) {
29000 if ($.isFunction(options.legend.sorted)) {
29001 entries.sort(options.legend.sorted);
29002 } else if (options.legend.sorted == "reverse") {
29003 entries.reverse();
29004 } else {
29005 var ascending = options.legend.sorted != "descending";
29006 entries.sort(function(a, b) {
29007 return a.label == b.label ? 0 : (
29008 (a.label < b.label) != ascending ? 1 : -1 // Logical XOR
29009 );
29010 });
29011 }
29012 }
29013
29014 // Generate markup for the list of entries, in their final order
29015
29016 for (var i = 0; i < entries.length; ++i) {
29017
29018 var entry = entries[i];
29019
29020 if (i % options.legend.noColumns == 0) {
29021 if (rowStarted)
29022 fragments.push('</tr>');
29023 fragments.push('<tr>');
29024 rowStarted = true;
29025 }
29026
29027 fragments.push(
29028 '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + entry.color + ';overflow:hidden"></div></div></td>' +
29029 '<td class="legendLabel">' + entry.label + '</td>'
29030 );
29031 }
29032
29033 if (rowStarted)
29034 fragments.push('</tr>');
29035
29036 if (fragments.length == 0)
29037 return;
29038
29039 var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
29040 if (options.legend.container != null)
29041 $(options.legend.container).html(table);
29042 else {
29043 var pos = "",
29044 p = options.legend.position,
29045 m = options.legend.margin;
29046 if (m[0] == null)
29047 m = [m, m];
29048 if (p.charAt(0) == "n")
29049 pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
29050 else if (p.charAt(0) == "s")
29051 pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
29052 if (p.charAt(1) == "e")
29053 pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
29054 else if (p.charAt(1) == "w")
29055 pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
29056 var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
29057 if (options.legend.backgroundOpacity != 0.0) {
29058 // put in the transparent background
29059 // separately to avoid blended labels and
29060 // label boxes
29061 var c = options.legend.backgroundColor;
29062 if (c == null) {
29063 c = options.grid.backgroundColor;
29064 if (c && typeof c == "string")
29065 c = $.color.parse(c);
29066 else
29067 c = $.color.extract(legend, 'background-color');
29068 c.a = 1;
29069 c = c.toString();
29070 }
29071 var div = legend.children();
29072 $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
29073 }
29074 }
29075 }
29076
29077
29078 // interactive features
29079
29080 var highlights = [],
29081 redrawTimeout = null;
29082
29083 // returns the data item the mouse is over, or null if none is found
29084 function findNearbyItem(mouseX, mouseY, seriesFilter) {
29085 var maxDistance = options.grid.mouseActiveRadius,
29086 smallestDistance = maxDistance * maxDistance + 1,
29087 item = null, foundPoint = false, i, j, ps;
29088
29089 for (i = series.length - 1; i >= 0; --i) {
29090 if (!seriesFilter(series[i]))
29091 continue;
29092
29093 var s = series[i],
29094 axisx = s.xaxis,
29095 axisy = s.yaxis,
29096 points = s.datapoints.points,
29097 mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
29098 my = axisy.c2p(mouseY),
29099 maxx = maxDistance / axisx.scale,
29100 maxy = maxDistance / axisy.scale;
29101
29102 ps = s.datapoints.pointsize;
29103 // with inverse transforms, we can't use the maxx/maxy
29104 // optimization, sadly
29105 if (axisx.options.inverseTransform)
29106 maxx = Number.MAX_VALUE;
29107 if (axisy.options.inverseTransform)
29108 maxy = Number.MAX_VALUE;
29109
29110 if (s.lines.show || s.points.show) {
29111 for (j = 0; j < points.length; j += ps) {
29112 var x = points[j], y = points[j + 1];
29113 if (x == null)
29114 continue;
29115
29116 // For points and lines, the cursor must be within a
29117 // certain distance to the data point
29118 if (x - mx > maxx || x - mx < -maxx ||
29119 y - my > maxy || y - my < -maxy)
29120 continue;
29121
29122 // We have to calculate distances in pixels, not in
29123 // data units, because the scales of the axes may be different
29124 var dx = Math.abs(axisx.p2c(x) - mouseX),
29125 dy = Math.abs(axisy.p2c(y) - mouseY),
29126 dist = dx * dx + dy * dy; // we save the sqrt
29127
29128 // use <= to ensure last point takes precedence
29129 // (last generally means on top of)
29130 if (dist < smallestDistance) {
29131 smallestDistance = dist;
29132 item = [i, j / ps];
29133 }
29134 }
29135 }
29136
29137 if (s.bars.show && !item) { // no other point can be nearby
29138
29139 var barLeft, barRight;
29140
29141 switch (s.bars.align) {
29142 case "left":
29143 barLeft = 0;
29144 break;
29145 case "right":
29146 barLeft = -s.bars.barWidth;
29147 break;
29148 default:
29149 barLeft = -s.bars.barWidth / 2;
29150 }
29151
29152 barRight = barLeft + s.bars.barWidth;
29153
29154 for (j = 0; j < points.length; j += ps) {
29155 var x = points[j], y = points[j + 1], b = points[j + 2];
29156 if (x == null)
29157 continue;
29158
29159 // for a bar graph, the cursor must be inside the bar
29160 if (series[i].bars.horizontal ?
29161 (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
29162 my >= y + barLeft && my <= y + barRight) :
29163 (mx >= x + barLeft && mx <= x + barRight &&
29164 my >= Math.min(b, y) && my <= Math.max(b, y)))
29165 item = [i, j / ps];
29166 }
29167 }
29168 }
29169
29170 if (item) {
29171 i = item[0];
29172 j = item[1];
29173 ps = series[i].datapoints.pointsize;
29174
29175 return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
29176 dataIndex: j,
29177 series: series[i],
29178 seriesIndex: i };
29179 }
29180
29181 return null;
29182 }
29183
29184 function onMouseMove(e) {
29185 if (options.grid.hoverable)
29186 triggerClickHoverEvent("plothover", e,
29187 function (s) { return s["hoverable"] != false; });
29188 }
29189
29190 function onMouseLeave(e) {
29191 if (options.grid.hoverable)
29192 triggerClickHoverEvent("plothover", e,
29193 function (s) { return false; });
29194 }
29195
29196 function onClick(e) {
29197 triggerClickHoverEvent("plotclick", e,
29198 function (s) { return s["clickable"] != false; });
29199 }
29200
29201 // trigger click or hover event (they send the same parameters
29202 // so we share their code)
29203 function triggerClickHoverEvent(eventname, event, seriesFilter) {
29204 var offset = eventHolder.offset(),
29205 canvasX = event.pageX - offset.left - plotOffset.left,
29206 canvasY = event.pageY - offset.top - plotOffset.top,
29207 pos = canvasToAxisCoords({ left: canvasX, top: canvasY });
29208
29209 pos.pageX = event.pageX;
29210 pos.pageY = event.pageY;
29211
29212 var item = findNearbyItem(canvasX, canvasY, seriesFilter);
29213
29214 if (item) {
29215 // fill in mouse pos for any listeners out there
29216 item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left, 10);
29217 item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10);
29218 }
29219
29220 if (options.grid.autoHighlight) {
29221 // clear auto-highlights
29222 for (var i = 0; i < highlights.length; ++i) {
29223 var h = highlights[i];
29224 if (h.auto == eventname &&
29225 !(item && h.series == item.series &&
29226 h.point[0] == item.datapoint[0] &&
29227 h.point[1] == item.datapoint[1]))
29228 unhighlight(h.series, h.point);
29229 }
29230
29231 if (item)
29232 highlight(item.series, item.datapoint, eventname);
29233 }
29234
29235 placeholder.trigger(eventname, [ pos, item ]);
29236 }
29237
29238 function triggerRedrawOverlay() {
29239 var t = options.interaction.redrawOverlayInterval;
29240 if (t == -1) { // skip event queue
29241 drawOverlay();
29242 return;
29243 }
29244
29245 if (!redrawTimeout)
29246 redrawTimeout = setTimeout(drawOverlay, t);
29247 }
29248
29249 function drawOverlay() {
29250 redrawTimeout = null;
29251
29252 // draw highlights
29253 octx.save();
29254 overlay.clear();
29255 octx.translate(plotOffset.left, plotOffset.top);
29256
29257 var i, hi;
29258 for (i = 0; i < highlights.length; ++i) {
29259 hi = highlights[i];
29260
29261 if (hi.series.bars.show)
29262 drawBarHighlight(hi.series, hi.point);
29263 else
29264 drawPointHighlight(hi.series, hi.point);
29265 }
29266 octx.restore();
29267
29268 executeHooks(hooks.drawOverlay, [octx]);
29269 }
29270
29271 function highlight(s, point, auto) {
29272 if (typeof s == "number")
29273 s = series[s];
29274
29275 if (typeof point == "number") {
29276 var ps = s.datapoints.pointsize;
29277 point = s.datapoints.points.slice(ps * point, ps * (point + 1));
29278 }
29279
29280 var i = indexOfHighlight(s, point);
29281 if (i == -1) {
29282 highlights.push({ series: s, point: point, auto: auto });
29283
29284 triggerRedrawOverlay();
29285 }
29286 else if (!auto)
29287 highlights[i].auto = false;
29288 }
29289
29290 function unhighlight(s, point) {
29291 if (s == null && point == null) {
29292 highlights = [];
29293 triggerRedrawOverlay();
29294 return;
29295 }
29296
29297 if (typeof s == "number")
29298 s = series[s];
29299
29300 if (typeof point == "number") {
29301 var ps = s.datapoints.pointsize;
29302 point = s.datapoints.points.slice(ps * point, ps * (point + 1));
29303 }
29304
29305 var i = indexOfHighlight(s, point);
29306 if (i != -1) {
29307 highlights.splice(i, 1);
29308
29309 triggerRedrawOverlay();
29310 }
29311 }
29312
29313 function indexOfHighlight(s, p) {
29314 for (var i = 0; i < highlights.length; ++i) {
29315 var h = highlights[i];
29316 if (h.series == s && h.point[0] == p[0]
29317 && h.point[1] == p[1])
29318 return i;
29319 }
29320 return -1;
29321 }
29322
29323 function drawPointHighlight(series, point) {
29324 var x = point[0], y = point[1],
29325 axisx = series.xaxis, axisy = series.yaxis,
29326 highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString();
29327
29328 if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
29329 return;
29330
29331 var pointRadius = series.points.radius + series.points.lineWidth / 2;
29332 octx.lineWidth = pointRadius;
29333 octx.strokeStyle = highlightColor;
29334 var radius = 1.5 * pointRadius;
29335 x = axisx.p2c(x);
29336 y = axisy.p2c(y);
29337
29338 octx.beginPath();
29339 if (series.points.symbol == "circle")
29340 octx.arc(x, y, radius, 0, 2 * Math.PI, false);
29341 else
29342 series.points.symbol(octx, x, y, radius, false);
29343 octx.closePath();
29344 octx.stroke();
29345 }
29346
29347 function drawBarHighlight(series, point) {
29348 var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(),
29349 fillStyle = highlightColor,
29350 barLeft;
29351
29352 switch (series.bars.align) {
29353 case "left":
29354 barLeft = 0;
29355 break;
29356 case "right":
29357 barLeft = -series.bars.barWidth;
29358 break;
29359 default:
29360 barLeft = -series.bars.barWidth / 2;
29361 }
29362
29363 octx.lineWidth = series.bars.lineWidth;
29364 octx.strokeStyle = highlightColor;
29365
29366 drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
29367 function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
29368 }
29369
29370 function getColorOrGradient(spec, bottom, top, defaultColor) {
29371 if (typeof spec == "string")
29372 return spec;
29373 else {
29374 // assume this is a gradient spec; IE currently only
29375 // supports a simple vertical gradient properly, so that's
29376 // what we support too
29377 var gradient = ctx.createLinearGradient(0, top, 0, bottom);
29378
29379 for (var i = 0, l = spec.colors.length; i < l; ++i) {
29380 var c = spec.colors[i];
29381 if (typeof c != "string") {
29382 var co = $.color.parse(defaultColor);
29383 if (c.brightness != null)
29384 co = co.scale('rgb', c.brightness);
29385 if (c.opacity != null)
29386 co.a *= c.opacity;
29387 c = co.toString();
29388 }
29389 gradient.addColorStop(i / (l - 1), c);
29390 }
29391
29392 return gradient;
29393 }
29394 }
29395 }
29396
29397 // Add the plot function to the top level of the jQuery object
29398
29399 $.plot = function(placeholder, data, options) {
29400 //var t0 = new Date();
29401 var plot = new Plot($(placeholder), data, options, $.plot.plugins);
29402 //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
29403 return plot;
29404 };
29405
29406 $.plot.version = "0.8.3-alpha";
29407
29408 $.plot.plugins = [];
29409
29410 // Also add the plot function as a chainable property
29411
29412 $.fn.plot = function(data, options) {
29413 return this.each(function() {
29414 $.plot(this, data, options);
29415 });
29416 };
29417
29418 // round to nearby lower multiple of base
29419 function floorInBase(n, base) {
29420 return base * Math.floor(n / base);
29421 }
29422
29423 })(jQuery);
29424 /* Flot plugin for rendering pie charts.
29425
29426 Copyright (c) 2007-2013 IOLA and Ole Laursen.
29427 Licensed under the MIT license.
29428
29429 The plugin assumes that each series has a single data value, and that each
29430 value is a positive integer or zero. Negative numbers don't make sense for a
29431 pie chart, and have unpredictable results. The values do NOT need to be
29432 passed in as percentages; the plugin will calculate the total and per-slice
29433 percentages internally.
29434
29435 * Created by Brian Medendorp
29436
29437 * Updated with contributions from btburnett3, Anthony Aragues and Xavi Ivars
29438
29439 The plugin supports these options:
29440
29441 series: {
29442 pie: {
29443 show: true/false
29444 radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
29445 innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
29446 startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
29447 tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
29448 offset: {
29449 top: integer value to move the pie up or down
29450 left: integer value to move the pie left or right, or 'auto'
29451 },
29452 stroke: {
29453 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
29454 width: integer pixel width of the stroke
29455 },
29456 label: {
29457 show: true/false, or 'auto'
29458 formatter: a user-defined function that modifies the text/style of the label text
29459 radius: 0-1 for percentage of fullsize, or a specified pixel length
29460 background: {
29461 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
29462 opacity: 0-1
29463 },
29464 threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
29465 },
29466 combine: {
29467 threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
29468 color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
29469 label: any text value of what the combined slice should be labeled
29470 }
29471 highlight: {
29472 opacity: 0-1
29473 }
29474 }
29475 }
29476
29477 More detail and specific examples can be found in the included HTML file.
29478
29479 */
29480
29481 (function($) {
29482
29483 // Maximum redraw attempts when fitting labels within the plot
29484
29485 var REDRAW_ATTEMPTS = 10;
29486
29487 // Factor by which to shrink the pie when fitting labels within the plot
29488
29489 var REDRAW_SHRINK = 0.95;
29490
29491 function init(plot) {
29492
29493 var canvas = null,
29494 target = null,
29495 options = null,
29496 maxRadius = null,
29497 centerLeft = null,
29498 centerTop = null,
29499 processed = false,
29500 ctx = null;
29501
29502 // interactive variables
29503
29504 var highlights = [];
29505
29506 // add hook to determine if pie plugin in enabled, and then perform necessary operations
29507
29508 plot.hooks.processOptions.push(function(plot, options) {
29509 if (options.series.pie.show) {
29510
29511 options.grid.show = false;
29512
29513 // set labels.show
29514
29515 if (options.series.pie.label.show == "auto") {
29516 if (options.legend.show) {
29517 options.series.pie.label.show = false;
29518 } else {
29519 options.series.pie.label.show = true;
29520 }
29521 }
29522
29523 // set radius
29524
29525 if (options.series.pie.radius == "auto") {
29526 if (options.series.pie.label.show) {
29527 options.series.pie.radius = 3/4;
29528 } else {
29529 options.series.pie.radius = 1;
29530 }
29531 }
29532
29533 // ensure sane tilt
29534
29535 if (options.series.pie.tilt > 1) {
29536 options.series.pie.tilt = 1;
29537 } else if (options.series.pie.tilt < 0) {
29538 options.series.pie.tilt = 0;
29539 }
29540 }
29541 });
29542
29543 plot.hooks.bindEvents.push(function(plot, eventHolder) {
29544 var options = plot.getOptions();
29545 if (options.series.pie.show) {
29546 if (options.grid.hoverable) {
29547 eventHolder.unbind("mousemove").mousemove(onMouseMove);
29548 }
29549 if (options.grid.clickable) {
29550 eventHolder.unbind("click").click(onClick);
29551 }
29552 }
29553 });
29554
29555 plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) {
29556 var options = plot.getOptions();
29557 if (options.series.pie.show) {
29558 processDatapoints(plot, series, data, datapoints);
29559 }
29560 });
29561
29562 plot.hooks.drawOverlay.push(function(plot, octx) {
29563 var options = plot.getOptions();
29564 if (options.series.pie.show) {
29565 drawOverlay(plot, octx);
29566 }
29567 });
29568
29569 plot.hooks.draw.push(function(plot, newCtx) {
29570 var options = plot.getOptions();
29571 if (options.series.pie.show) {
29572 draw(plot, newCtx);
29573 }
29574 });
29575
29576 function processDatapoints(plot, series, datapoints) {
29577 if (!processed) {
29578 processed = true;
29579 canvas = plot.getCanvas();
29580 target = $(canvas).parent();
29581 options = plot.getOptions();
29582 plot.setData(combine(plot.getData()));
29583 }
29584 }
29585
29586 function combine(data) {
29587
29588 var total = 0,
29589 combined = 0,
29590 numCombined = 0,
29591 color = options.series.pie.combine.color,
29592 newdata = [];
29593
29594 // Fix up the raw data from Flot, ensuring the data is numeric
29595
29596 for (var i = 0; i < data.length; ++i) {
29597
29598 var value = data[i].data;
29599
29600 // If the data is an array, we'll assume that it's a standard
29601 // Flot x-y pair, and are concerned only with the second value.
29602
29603 // Note how we use the original array, rather than creating a
29604 // new one; this is more efficient and preserves any extra data
29605 // that the user may have stored in higher indexes.
29606
29607 if ($.isArray(value) && value.length == 1) {
29608 value = value[0];
29609 }
29610
29611 if ($.isArray(value)) {
29612 // Equivalent to $.isNumeric() but compatible with jQuery < 1.7
29613 if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) {
29614 value[1] = +value[1];
29615 } else {
29616 value[1] = 0;
29617 }
29618 } else if (!isNaN(parseFloat(value)) && isFinite(value)) {
29619 value = [1, +value];
29620 } else {
29621 value = [1, 0];
29622 }
29623
29624 data[i].data = [value];
29625 }
29626
29627 // Sum up all the slices, so we can calculate percentages for each
29628
29629 for (var i = 0; i < data.length; ++i) {
29630 total += data[i].data[0][1];
29631 }
29632
29633 // Count the number of slices with percentages below the combine
29634 // threshold; if it turns out to be just one, we won't combine.
29635
29636 for (var i = 0; i < data.length; ++i) {
29637 var value = data[i].data[0][1];
29638 if (value / total <= options.series.pie.combine.threshold) {
29639 combined += value;
29640 numCombined++;
29641 if (!color) {
29642 color = data[i].color;
29643 }
29644 }
29645 }
29646
29647 for (var i = 0; i < data.length; ++i) {
29648 var value = data[i].data[0][1];
29649 if (numCombined < 2 || value / total > options.series.pie.combine.threshold) {
29650 newdata.push(
29651 $.extend(data[i], { /* extend to allow keeping all other original data values
29652 and using them e.g. in labelFormatter. */
29653 data: [[1, value]],
29654 color: data[i].color,
29655 label: data[i].label,
29656 angle: value * Math.PI * 2 / total,
29657 percent: value / (total / 100)
29658 })
29659 );
29660 }
29661 }
29662
29663 if (numCombined > 1) {
29664 newdata.push({
29665 data: [[1, combined]],
29666 color: color,
29667 label: options.series.pie.combine.label,
29668 angle: combined * Math.PI * 2 / total,
29669 percent: combined / (total / 100)
29670 });
29671 }
29672
29673 return newdata;
29674 }
29675
29676 function draw(plot, newCtx) {
29677
29678 if (!target) {
29679 return; // if no series were passed
29680 }
29681
29682 var canvasWidth = plot.getPlaceholder().width(),
29683 canvasHeight = plot.getPlaceholder().height(),
29684 legendWidth = target.children().filter(".legend").children().width() || 0;
29685
29686 ctx = newCtx;
29687
29688 // WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE!
29689
29690 // When combining smaller slices into an 'other' slice, we need to
29691 // add a new series. Since Flot gives plugins no way to modify the
29692 // list of series, the pie plugin uses a hack where the first call
29693 // to processDatapoints results in a call to setData with the new
29694 // list of series, then subsequent processDatapoints do nothing.
29695
29696 // The plugin-global 'processed' flag is used to control this hack;
29697 // it starts out false, and is set to true after the first call to
29698 // processDatapoints.
29699
29700 // Unfortunately this turns future setData calls into no-ops; they
29701 // call processDatapoints, the flag is true, and nothing happens.
29702
29703 // To fix this we'll set the flag back to false here in draw, when
29704 // all series have been processed, so the next sequence of calls to
29705 // processDatapoints once again starts out with a slice-combine.
29706 // This is really a hack; in 0.9 we need to give plugins a proper
29707 // way to modify series before any processing begins.
29708
29709 processed = false;
29710
29711 // calculate maximum radius and center point
29712
29713 maxRadius = Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2;
29714 centerTop = canvasHeight / 2 + options.series.pie.offset.top;
29715 centerLeft = canvasWidth / 2;
29716
29717 if (options.series.pie.offset.left == "auto") {
29718 if (options.legend.position.match("w")) {
29719 centerLeft += legendWidth / 2;
29720 } else {
29721 centerLeft -= legendWidth / 2;
29722 }
29723 if (centerLeft < maxRadius) {
29724 centerLeft = maxRadius;
29725 } else if (centerLeft > canvasWidth - maxRadius) {
29726 centerLeft = canvasWidth - maxRadius;
29727 }
29728 } else {
29729 centerLeft += options.series.pie.offset.left;
29730 }
29731
29732 var slices = plot.getData(),
29733 attempts = 0;
29734
29735 // Keep shrinking the pie's radius until drawPie returns true,
29736 // indicating that all the labels fit, or we try too many times.
29737
29738 do {
29739 if (attempts > 0) {
29740 maxRadius *= REDRAW_SHRINK;
29741 }
29742 attempts += 1;
29743 clear();
29744 if (options.series.pie.tilt <= 0.8) {
29745 drawShadow();
29746 }
29747 } while (!drawPie() && attempts < REDRAW_ATTEMPTS)
29748
29749 if (attempts >= REDRAW_ATTEMPTS) {
29750 clear();
29751 target.prepend("<div class='error'>Could not draw pie with labels contained inside canvas</div>");
29752 }
29753
29754 if (plot.setSeries && plot.insertLegend) {
29755 plot.setSeries(slices);
29756 plot.insertLegend();
29757 }
29758
29759 // we're actually done at this point, just defining internal functions at this point
29760
29761 function clear() {
29762 ctx.clearRect(0, 0, canvasWidth, canvasHeight);
29763 target.children().filter(".pieLabel, .pieLabelBackground").remove();
29764 }
29765
29766 function drawShadow() {
29767
29768 var shadowLeft = options.series.pie.shadow.left;
29769 var shadowTop = options.series.pie.shadow.top;
29770 var edge = 10;
29771 var alpha = options.series.pie.shadow.alpha;
29772 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
29773
29774 if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) {
29775 return; // shadow would be outside canvas, so don't draw it
29776 }
29777
29778 ctx.save();
29779 ctx.translate(shadowLeft,shadowTop);
29780 ctx.globalAlpha = alpha;
29781 ctx.fillStyle = "#000";
29782
29783 // center and rotate to starting position
29784
29785 ctx.translate(centerLeft,centerTop);
29786 ctx.scale(1, options.series.pie.tilt);
29787
29788 //radius -= edge;
29789
29790 for (var i = 1; i <= edge; i++) {
29791 ctx.beginPath();
29792 ctx.arc(0, 0, radius, 0, Math.PI * 2, false);
29793 ctx.fill();
29794 radius -= i;
29795 }
29796
29797 ctx.restore();
29798 }
29799
29800 function drawPie() {
29801
29802 var startAngle = Math.PI * options.series.pie.startAngle;
29803 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
29804
29805 // center and rotate to starting position
29806
29807 ctx.save();
29808 ctx.translate(centerLeft,centerTop);
29809 ctx.scale(1, options.series.pie.tilt);
29810 //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
29811
29812 // draw slices
29813
29814 ctx.save();
29815 var currentAngle = startAngle;
29816 for (var i = 0; i < slices.length; ++i) {
29817 slices[i].startAngle = currentAngle;
29818 drawSlice(slices[i].angle, slices[i].color, true);
29819 }
29820 ctx.restore();
29821
29822 // draw slice outlines
29823
29824 if (options.series.pie.stroke.width > 0) {
29825 ctx.save();
29826 ctx.lineWidth = options.series.pie.stroke.width;
29827 currentAngle = startAngle;
29828 for (var i = 0; i < slices.length; ++i) {
29829 drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
29830 }
29831 ctx.restore();
29832 }
29833
29834 // draw donut hole
29835
29836 drawDonutHole(ctx);
29837
29838 ctx.restore();
29839
29840 // Draw the labels, returning true if they fit within the plot
29841
29842 if (options.series.pie.label.show) {
29843 return drawLabels();
29844 } else return true;
29845
29846 function drawSlice(angle, color, fill) {
29847
29848 if (angle <= 0 || isNaN(angle)) {
29849 return;
29850 }
29851
29852 if (fill) {
29853 ctx.fillStyle = color;
29854 } else {
29855 ctx.strokeStyle = color;
29856 ctx.lineJoin = "round";
29857 }
29858
29859 ctx.beginPath();
29860 if (Math.abs(angle - Math.PI * 2) > 0.000000001) {
29861 ctx.moveTo(0, 0); // Center of the pie
29862 }
29863
29864 //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera
29865 ctx.arc(0, 0, radius,currentAngle, currentAngle + angle / 2, false);
29866 ctx.arc(0, 0, radius,currentAngle + angle / 2, currentAngle + angle, false);
29867 ctx.closePath();
29868 //ctx.rotate(angle); // This doesn't work properly in Opera
29869 currentAngle += angle;
29870
29871 if (fill) {
29872 ctx.fill();
29873 } else {
29874 ctx.stroke();
29875 }
29876 }
29877
29878 function drawLabels() {
29879
29880 var currentAngle = startAngle;
29881 var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius;
29882
29883 for (var i = 0; i < slices.length; ++i) {
29884 if (slices[i].percent >= options.series.pie.label.threshold * 100) {
29885 if (!drawLabel(slices[i], currentAngle, i)) {
29886 return false;
29887 }
29888 }
29889 currentAngle += slices[i].angle;
29890 }
29891
29892 return true;
29893
29894 function drawLabel(slice, startAngle, index) {
29895
29896 if (slice.data[0][1] == 0) {
29897 return true;
29898 }
29899
29900 // format label text
29901
29902 var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
29903
29904 if (lf) {
29905 text = lf(slice.label, slice);
29906 } else {
29907 text = slice.label;
29908 }
29909
29910 if (plf) {
29911 text = plf(text, slice);
29912 }
29913
29914 var halfAngle = ((startAngle + slice.angle) + startAngle) / 2;
29915 var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
29916 var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
29917
29918 var html = "<span class='pieLabel' id='pieLabel" + index + "' style='position:absolute;top:" + y + "px;left:" + x + "px;'>" + text + "</span>";
29919 target.append(html);
29920
29921 var label = target.children("#pieLabel" + index);
29922 var labelTop = (y - label.height() / 2);
29923 var labelLeft = (x - label.width() / 2);
29924
29925 label.css("top", labelTop);
29926 label.css("left", labelLeft);
29927
29928 // check to make sure that the label is not outside the canvas
29929
29930 if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) {
29931 return false;
29932 }
29933
29934 if (options.series.pie.label.background.opacity != 0) {
29935
29936 // put in the transparent background separately to avoid blended labels and label boxes
29937
29938 var c = options.series.pie.label.background.color;
29939
29940 if (c == null) {
29941 c = slice.color;
29942 }
29943
29944 var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;";
29945 $("<div class='pieLabelBackground' style='position:absolute;width:" + label.width() + "px;height:" + label.height() + "px;" + pos + "background-color:" + c + ";'></div>")
29946 .css("opacity", options.series.pie.label.background.opacity)
29947 .insertBefore(label);
29948 }
29949
29950 return true;
29951 } // end individual label function
29952 } // end drawLabels function
29953 } // end drawPie function
29954 } // end draw function
29955
29956 // Placed here because it needs to be accessed from multiple locations
29957
29958 function drawDonutHole(layer) {
29959 if (options.series.pie.innerRadius > 0) {
29960
29961 // subtract the center
29962
29963 layer.save();
29964 var innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
29965 layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color
29966 layer.beginPath();
29967 layer.fillStyle = options.series.pie.stroke.color;
29968 layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
29969 layer.fill();
29970 layer.closePath();
29971 layer.restore();
29972
29973 // add inner stroke
29974
29975 layer.save();
29976 layer.beginPath();
29977 layer.strokeStyle = options.series.pie.stroke.color;
29978 layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
29979 layer.stroke();
29980 layer.closePath();
29981 layer.restore();
29982
29983 // TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
29984 }
29985 }
29986
29987 //-- Additional Interactive related functions --
29988
29989 function isPointInPoly(poly, pt) {
29990 for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
29991 ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
29992 && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
29993 && (c = !c);
29994 return c;
29995 }
29996
29997 function findNearbySlice(mouseX, mouseY) {
29998
29999 var slices = plot.getData(),
30000 options = plot.getOptions(),
30001 radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius,
30002 x, y;
30003
30004 for (var i = 0; i < slices.length; ++i) {
30005
30006 var s = slices[i];
30007
30008 if (s.pie.show) {
30009
30010 ctx.save();
30011 ctx.beginPath();
30012 ctx.moveTo(0, 0); // Center of the pie
30013 //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
30014 ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle / 2, false);
30015 ctx.arc(0, 0, radius, s.startAngle + s.angle / 2, s.startAngle + s.angle, false);
30016 ctx.closePath();
30017 x = mouseX - centerLeft;
30018 y = mouseY - centerTop;
30019
30020 if (ctx.isPointInPath) {
30021 if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) {
30022 ctx.restore();
30023 return {
30024 datapoint: [s.percent, s.data],
30025 dataIndex: 0,
30026 series: s,
30027 seriesIndex: i
30028 };
30029 }
30030 } else {
30031
30032 // excanvas for IE doesn;t support isPointInPath, this is a workaround.
30033
30034 var p1X = radius * Math.cos(s.startAngle),
30035 p1Y = radius * Math.sin(s.startAngle),
30036 p2X = radius * Math.cos(s.startAngle + s.angle / 4),
30037 p2Y = radius * Math.sin(s.startAngle + s.angle / 4),
30038 p3X = radius * Math.cos(s.startAngle + s.angle / 2),
30039 p3Y = radius * Math.sin(s.startAngle + s.angle / 2),
30040 p4X = radius * Math.cos(s.startAngle + s.angle / 1.5),
30041 p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5),
30042 p5X = radius * Math.cos(s.startAngle + s.angle),
30043 p5Y = radius * Math.sin(s.startAngle + s.angle),
30044 arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]],
30045 arrPoint = [x, y];
30046
30047 // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
30048
30049 if (isPointInPoly(arrPoly, arrPoint)) {
30050 ctx.restore();
30051 return {
30052 datapoint: [s.percent, s.data],
30053 dataIndex: 0,
30054 series: s,
30055 seriesIndex: i
30056 };
30057 }
30058 }
30059
30060 ctx.restore();
30061 }
30062 }
30063
30064 return null;
30065 }
30066
30067 function onMouseMove(e) {
30068 triggerClickHoverEvent("plothover", e);
30069 }
30070
30071 function onClick(e) {
30072 triggerClickHoverEvent("plotclick", e);
30073 }
30074
30075 // trigger click or hover event (they send the same parameters so we share their code)
30076
30077 function triggerClickHoverEvent(eventname, e) {
30078
30079 var offset = plot.offset();
30080 var canvasX = parseInt(e.pageX - offset.left);
30081 var canvasY = parseInt(e.pageY - offset.top);
30082 var item = findNearbySlice(canvasX, canvasY);
30083
30084 if (options.grid.autoHighlight) {
30085
30086 // clear auto-highlights
30087
30088 for (var i = 0; i < highlights.length; ++i) {
30089 var h = highlights[i];
30090 if (h.auto == eventname && !(item && h.series == item.series)) {
30091 unhighlight(h.series);
30092 }
30093 }
30094 }
30095
30096 // highlight the slice
30097
30098 if (item) {
30099 highlight(item.series, eventname);
30100 }
30101
30102 // trigger any hover bind events
30103
30104 var pos = { pageX: e.pageX, pageY: e.pageY };
30105 target.trigger(eventname, [pos, item]);
30106 }
30107
30108 function highlight(s, auto) {
30109 //if (typeof s == "number") {
30110 // s = series[s];
30111 //}
30112
30113 var i = indexOfHighlight(s);
30114
30115 if (i == -1) {
30116 highlights.push({ series: s, auto: auto });
30117 plot.triggerRedrawOverlay();
30118 } else if (!auto) {
30119 highlights[i].auto = false;
30120 }
30121 }
30122
30123 function unhighlight(s) {
30124 if (s == null) {
30125 highlights = [];
30126 plot.triggerRedrawOverlay();
30127 }
30128
30129 //if (typeof s == "number") {
30130 // s = series[s];
30131 //}
30132
30133 var i = indexOfHighlight(s);
30134
30135 if (i != -1) {
30136 highlights.splice(i, 1);
30137 plot.triggerRedrawOverlay();
30138 }
30139 }
30140
30141 function indexOfHighlight(s) {
30142 for (var i = 0; i < highlights.length; ++i) {
30143 var h = highlights[i];
30144 if (h.series == s)
30145 return i;
30146 }
30147 return -1;
30148 }
30149
30150 function drawOverlay(plot, octx) {
30151
30152 var options = plot.getOptions();
30153
30154 var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
30155
30156 octx.save();
30157 octx.translate(centerLeft, centerTop);
30158 octx.scale(1, options.series.pie.tilt);
30159
30160 for (var i = 0; i < highlights.length; ++i) {
30161 drawHighlight(highlights[i].series);
30162 }
30163
30164 drawDonutHole(octx);
30165
30166 octx.restore();
30167
30168 function drawHighlight(series) {
30169
30170 if (series.angle <= 0 || isNaN(series.angle)) {
30171 return;
30172 }
30173
30174 //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
30175 octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor
30176 octx.beginPath();
30177 if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) {
30178 octx.moveTo(0, 0); // Center of the pie
30179 }
30180 octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle / 2, false);
30181 octx.arc(0, 0, radius, series.startAngle + series.angle / 2, series.startAngle + series.angle, false);
30182 octx.closePath();
30183 octx.fill();
30184 }
30185 }
30186 } // end init (plugin body)
30187
30188 // define pie specific options and their default values
30189
30190 var options = {
30191 series: {
30192 pie: {
30193 show: false,
30194 radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
30195 innerRadius: 0, /* for donut */
30196 startAngle: 3/2,
30197 tilt: 1,
30198 shadow: {
30199 left: 5, // shadow left offset
30200 top: 15, // shadow top offset
30201 alpha: 0.02 // shadow alpha
30202 },
30203 offset: {
30204 top: 0,
30205 left: "auto"
30206 },
30207 stroke: {
30208 color: "#fff",
30209 width: 1
30210 },
30211 label: {
30212 show: "auto",
30213 formatter: function(label, slice) {
30214 return "<div style='font-size:x-small;text-align:center;padding:2px;color:" + slice.color + ";'>" + label + "<br/>" + Math.round(slice.percent) + "%</div>";
30215 }, // formatter function
30216 radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
30217 background: {
30218 color: null,
30219 opacity: 0
30220 },
30221 threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow)
30222 },
30223 combine: {
30224 threshold: -1, // percentage at which to combine little slices into one larger slice
30225 color: null, // color to give the new slice (auto-generated if null)
30226 label: "Other" // label to give the new slice
30227 },
30228 highlight: {
30229 //color: "#fff", // will add this functionality once parseColor is available
30230 opacity: 0.5
30231 }
30232 }
30233 }
30234 };
30235
30236 $.plot.plugins.push({
30237 init: init,
30238 options: options,
30239 name: "pie",
30240 version: "1.1"
30241 });
30242
30243 })(jQuery);
30244 /* Flot plugin for automatically redrawing plots as the placeholder resizes.
30245
30246 Copyright (c) 2007-2013 IOLA and Ole Laursen.
30247 Licensed under the MIT license.
30248
30249 It works by listening for changes on the placeholder div (through the jQuery
30250 resize event plugin) - if the size changes, it will redraw the plot.
30251
30252 There are no options. If you need to disable the plugin for some plots, you
30253 can just fix the size of their placeholders.
30254
30255 */
30256
30257 /* Inline dependency:
30258 * jQuery resize event - v1.1 - 3/14/2010
30259 * http://benalman.com/projects/jquery-resize-plugin/
30260 *
30261 * Copyright (c) 2010 "Cowboy" Ben Alman
30262 * Dual licensed under the MIT and GPL licenses.
30263 * http://benalman.com/about/license/
30264 */
30265
30266 (function($,t,n){function p(){for(var n=r.length-1;n>=0;n--){var o=$(r[n]);if(o[0]==t||o.is(":visible")){var h=o.width(),d=o.height(),v=o.data(a);!v||h===v.w&&d===v.h?i[f]=i[l]:(i[f]=i[c],o.trigger(u,[v.w=h,v.h=d]))}else v=o.data(a),v.w=0,v.h=0}s!==null&&(s=t.requestAnimationFrame(p))}var r=[],i=$.resize=$.extend($.resize,{}),s,o="setTimeout",u="resize",a=u+"-special-event",f="delay",l="pendingDelay",c="activeDelay",h="throttleWindow";i[l]=250,i[c]=20,i[f]=i[l],i[h]=!0,$.event.special[u]={setup:function(){if(!i[h]&&this[o])return!1;var t=$(this);r.push(this),t.data(a,{w:t.width(),h:t.height()}),r.length===1&&(s=n,p())},teardown:function(){if(!i[h]&&this[o])return!1;var t=$(this);for(var n=r.length-1;n>=0;n--)if(r[n]==this){r.splice(n,1);break}t.removeData(a),r.length||(cancelAnimationFrame(s),s=null)},add:function(t){function s(t,i,s){var o=$(this),u=o.data(a);u.w=i!==n?i:o.width(),u.h=s!==n?s:o.height(),r.apply(this,arguments)}if(!i[h]&&this[o])return!1;var r;if($.isFunction(t))return r=t,s;r=t.handler,t.handler=s}},t.requestAnimationFrame||(t.requestAnimationFrame=function(){return t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||t.msRequestAnimationFrame||function(e,n){return t.setTimeout(e,i[f])}}()),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(){return t.webkitCancelRequestAnimationFrame||t.mozCancelRequestAnimationFrame||t.oCancelRequestAnimationFrame||t.msCancelRequestAnimationFrame||clearTimeout}())})(jQuery,this);
30267
30268 (function ($) {
30269 var options = { }; // no options
30270
30271 function init(plot) {
30272 function onResize() {
30273 var placeholder = plot.getPlaceholder();
30274
30275 // somebody might have hidden us and we can't plot
30276 // when we don't have the dimensions
30277 if (placeholder.width() == 0 || placeholder.height() == 0)
30278 return;
30279
30280 plot.resize();
30281 plot.setupGrid();
30282 plot.draw();
30283 }
30284
30285 function bindEvents(plot, eventHolder) {
30286 plot.getPlaceholder().resize(onResize);
30287 }
30288
30289 function shutdown(plot, eventHolder) {
30290 plot.getPlaceholder().unbind("resize", onResize);
30291 }
30292
30293 plot.hooks.bindEvents.push(bindEvents);
30294 plot.hooks.shutdown.push(shutdown);
30295 }
30296
30297 $.plot.plugins.push({
30298 init: init,
30299 options: options,
30300 name: 'resize',
30301 version: '1.0'
30302 });
30303 })(jQuery);
30304 /* Flot plugin for selecting regions of a plot.
30305
30306 Copyright (c) 2007-2013 IOLA and Ole Laursen.
30307 Licensed under the MIT license.
30308
30309 The plugin supports these options:
30310
30311 selection: {
30312 mode: null or "x" or "y" or "xy",
30313 color: color,
30314 shape: "round" or "miter" or "bevel",
30315 minSize: number of pixels
30316 }
30317
30318 Selection support is enabled by setting the mode to one of "x", "y" or "xy".
30319 In "x" mode, the user will only be able to specify the x range, similarly for
30320 "y" mode. For "xy", the selection becomes a rectangle where both ranges can be
30321 specified. "color" is color of the selection (if you need to change the color
30322 later on, you can get to it with plot.getOptions().selection.color). "shape"
30323 is the shape of the corners of the selection.
30324
30325 "minSize" is the minimum size a selection can be in pixels. This value can
30326 be customized to determine the smallest size a selection can be and still
30327 have the selection rectangle be displayed. When customizing this value, the
30328 fact that it refers to pixels, not axis units must be taken into account.
30329 Thus, for example, if there is a bar graph in time mode with BarWidth set to 1
30330 minute, setting "minSize" to 1 will not make the minimum selection size 1
30331 minute, but rather 1 pixel. Note also that setting "minSize" to 0 will prevent
30332 "plotunselected" events from being fired when the user clicks the mouse without
30333 dragging.
30334
30335 When selection support is enabled, a "plotselected" event will be emitted on
30336 the DOM element you passed into the plot function. The event handler gets a
30337 parameter with the ranges selected on the axes, like this:
30338
30339 placeholder.bind( "plotselected", function( event, ranges ) {
30340 alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
30341 // similar for yaxis - with multiple axes, the extra ones are in
30342 // x2axis, x3axis, ...
30343 });
30344
30345 The "plotselected" event is only fired when the user has finished making the
30346 selection. A "plotselecting" event is fired during the process with the same
30347 parameters as the "plotselected" event, in case you want to know what's
30348 happening while it's happening,
30349
30350 A "plotunselected" event with no arguments is emitted when the user clicks the
30351 mouse to remove the selection. As stated above, setting "minSize" to 0 will
30352 destroy this behavior.
30353
30354 The plugin allso adds the following methods to the plot object:
30355
30356 - setSelection( ranges, preventEvent )
30357
30358 Set the selection rectangle. The passed in ranges is on the same form as
30359 returned in the "plotselected" event. If the selection mode is "x", you
30360 should put in either an xaxis range, if the mode is "y" you need to put in
30361 an yaxis range and both xaxis and yaxis if the selection mode is "xy", like
30362 this:
30363
30364 setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
30365
30366 setSelection will trigger the "plotselected" event when called. If you don't
30367 want that to happen, e.g. if you're inside a "plotselected" handler, pass
30368 true as the second parameter. If you are using multiple axes, you can
30369 specify the ranges on any of those, e.g. as x2axis/x3axis/... instead of
30370 xaxis, the plugin picks the first one it sees.
30371
30372 - clearSelection( preventEvent )
30373
30374 Clear the selection rectangle. Pass in true to avoid getting a
30375 "plotunselected" event.
30376
30377 - getSelection()
30378
30379 Returns the current selection in the same format as the "plotselected"
30380 event. If there's currently no selection, the function returns null.
30381
30382 */
30383
30384 (function ($) {
30385 function init(plot) {
30386 var selection = {
30387 first: { x: -1, y: -1}, second: { x: -1, y: -1},
30388 show: false,
30389 active: false
30390 };
30391
30392 // FIXME: The drag handling implemented here should be
30393 // abstracted out, there's some similar code from a library in
30394 // the navigation plugin, this should be massaged a bit to fit
30395 // the Flot cases here better and reused. Doing this would
30396 // make this plugin much slimmer.
30397 var savedhandlers = {};
30398
30399 var mouseUpHandler = null;
30400
30401 function onMouseMove(e) {
30402 if (selection.active) {
30403 updateSelection(e);
30404
30405 plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
30406 }
30407 }
30408
30409 function onMouseDown(e) {
30410 if (e.which != 1) // only accept left-click
30411 return;
30412
30413 // cancel out any text selections
30414 document.body.focus();
30415
30416 // prevent text selection and drag in old-school browsers
30417 if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
30418 savedhandlers.onselectstart = document.onselectstart;
30419 document.onselectstart = function () { return false; };
30420 }
30421 if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
30422 savedhandlers.ondrag = document.ondrag;
30423 document.ondrag = function () { return false; };
30424 }
30425
30426 setSelectionPos(selection.first, e);
30427
30428 selection.active = true;
30429
30430 // this is a bit silly, but we have to use a closure to be
30431 // able to whack the same handler again
30432 mouseUpHandler = function (e) { onMouseUp(e); };
30433
30434 $(document).one("mouseup", mouseUpHandler);
30435 }
30436
30437 function onMouseUp(e) {
30438 mouseUpHandler = null;
30439
30440 // revert drag stuff for old-school browsers
30441 if (document.onselectstart !== undefined)
30442 document.onselectstart = savedhandlers.onselectstart;
30443 if (document.ondrag !== undefined)
30444 document.ondrag = savedhandlers.ondrag;
30445
30446 // no more dragging
30447 selection.active = false;
30448 updateSelection(e);
30449
30450 if (selectionIsSane())
30451 triggerSelectedEvent();
30452 else {
30453 // this counts as a clear
30454 plot.getPlaceholder().trigger("plotunselected", [ ]);
30455 plot.getPlaceholder().trigger("plotselecting", [ null ]);
30456 }
30457
30458 return false;
30459 }
30460
30461 function getSelection() {
30462 if (!selectionIsSane())
30463 return null;
30464
30465 if (!selection.show) return null;
30466
30467 var r = {}, c1 = selection.first, c2 = selection.second;
30468 $.each(plot.getAxes(), function (name, axis) {
30469 if (axis.used) {
30470 var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
30471 r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
30472 }
30473 });
30474 return r;
30475 }
30476
30477 function triggerSelectedEvent() {
30478 var r = getSelection();
30479
30480 plot.getPlaceholder().trigger("plotselected", [ r ]);
30481
30482 // backwards-compat stuff, to be removed in future
30483 if (r.xaxis && r.yaxis)
30484 plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
30485 }
30486
30487 function clamp(min, value, max) {
30488 return value < min ? min: (value > max ? max: value);
30489 }
30490
30491 function setSelectionPos(pos, e) {
30492 var o = plot.getOptions();
30493 var offset = plot.getPlaceholder().offset();
30494 var plotOffset = plot.getPlotOffset();
30495 pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
30496 pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
30497
30498 if (o.selection.mode == "y")
30499 pos.x = pos == selection.first ? 0 : plot.width();
30500
30501 if (o.selection.mode == "x")
30502 pos.y = pos == selection.first ? 0 : plot.height();
30503 }
30504
30505 function updateSelection(pos) {
30506 if (pos.pageX == null)
30507 return;
30508
30509 setSelectionPos(selection.second, pos);
30510 if (selectionIsSane()) {
30511 selection.show = true;
30512 plot.triggerRedrawOverlay();
30513 }
30514 else
30515 clearSelection(true);
30516 }
30517
30518 function clearSelection(preventEvent) {
30519 if (selection.show) {
30520 selection.show = false;
30521 plot.triggerRedrawOverlay();
30522 if (!preventEvent)
30523 plot.getPlaceholder().trigger("plotunselected", [ ]);
30524 }
30525 }
30526
30527 // function taken from markings support in Flot
30528 function extractRange(ranges, coord) {
30529 var axis, from, to, key, axes = plot.getAxes();
30530
30531 for (var k in axes) {
30532 axis = axes[k];
30533 if (axis.direction == coord) {
30534 key = coord + axis.n + "axis";
30535 if (!ranges[key] && axis.n == 1)
30536 key = coord + "axis"; // support x1axis as xaxis
30537 if (ranges[key]) {
30538 from = ranges[key].from;
30539 to = ranges[key].to;
30540 break;
30541 }
30542 }
30543 }
30544
30545 // backwards-compat stuff - to be removed in future
30546 if (!ranges[key]) {
30547 axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
30548 from = ranges[coord + "1"];
30549 to = ranges[coord + "2"];
30550 }
30551
30552 // auto-reverse as an added bonus
30553 if (from != null && to != null && from > to) {
30554 var tmp = from;
30555 from = to;
30556 to = tmp;
30557 }
30558
30559 return { from: from, to: to, axis: axis };
30560 }
30561
30562 function setSelection(ranges, preventEvent) {
30563 var axis, range, o = plot.getOptions();
30564
30565 if (o.selection.mode == "y") {
30566 selection.first.x = 0;
30567 selection.second.x = plot.width();
30568 }
30569 else {
30570 range = extractRange(ranges, "x");
30571
30572 selection.first.x = range.axis.p2c(range.from);
30573 selection.second.x = range.axis.p2c(range.to);
30574 }
30575
30576 if (o.selection.mode == "x") {
30577 selection.first.y = 0;
30578 selection.second.y = plot.height();
30579 }
30580 else {
30581 range = extractRange(ranges, "y");
30582
30583 selection.first.y = range.axis.p2c(range.from);
30584 selection.second.y = range.axis.p2c(range.to);
30585 }
30586
30587 selection.show = true;
30588 plot.triggerRedrawOverlay();
30589 if (!preventEvent && selectionIsSane())
30590 triggerSelectedEvent();
30591 }
30592
30593 function selectionIsSane() {
30594 var minSize = plot.getOptions().selection.minSize;
30595 return Math.abs(selection.second.x - selection.first.x) >= minSize &&
30596 Math.abs(selection.second.y - selection.first.y) >= minSize;
30597 }
30598
30599 plot.clearSelection = clearSelection;
30600 plot.setSelection = setSelection;
30601 plot.getSelection = getSelection;
30602
30603 plot.hooks.bindEvents.push(function(plot, eventHolder) {
30604 var o = plot.getOptions();
30605 if (o.selection.mode != null) {
30606 eventHolder.mousemove(onMouseMove);
30607 eventHolder.mousedown(onMouseDown);
30608 }
30609 });
30610
30611
30612 plot.hooks.drawOverlay.push(function (plot, ctx) {
30613 // draw selection
30614 if (selection.show && selectionIsSane()) {
30615 var plotOffset = plot.getPlotOffset();
30616 var o = plot.getOptions();
30617
30618 ctx.save();
30619 ctx.translate(plotOffset.left, plotOffset.top);
30620
30621 var c = $.color.parse(o.selection.color);
30622
30623 ctx.strokeStyle = c.scale('a', 0.8).toString();
30624 ctx.lineWidth = 1;
30625 ctx.lineJoin = o.selection.shape;
30626 ctx.fillStyle = c.scale('a', 0.4).toString();
30627
30628 var x = Math.min(selection.first.x, selection.second.x) + 0.5,
30629 y = Math.min(selection.first.y, selection.second.y) + 0.5,
30630 w = Math.abs(selection.second.x - selection.first.x) - 1,
30631 h = Math.abs(selection.second.y - selection.first.y) - 1;
30632
30633 ctx.fillRect(x, y, w, h);
30634 ctx.strokeRect(x, y, w, h);
30635
30636 ctx.restore();
30637 }
30638 });
30639
30640 plot.hooks.shutdown.push(function (plot, eventHolder) {
30641 eventHolder.unbind("mousemove", onMouseMove);
30642 eventHolder.unbind("mousedown", onMouseDown);
30643
30644 if (mouseUpHandler)
30645 $(document).unbind("mouseup", mouseUpHandler);
30646 });
30647
30648 }
30649
30650 $.plot.plugins.push({
30651 init: init,
30652 options: {
30653 selection: {
30654 mode: null, // one of null, "x", "y" or "xy"
30655 color: "#e8cfac",
30656 shape: "round", // one of "round", "miter", or "bevel"
30657 minSize: 5 // minimum number of pixels
30658 }
30659 },
30660 name: 'selection',
30661 version: '1.1'
30662 });
30663 })(jQuery);
30664 /* Pretty handling of time axes.
30665
30666 Copyright (c) 2007-2013 IOLA and Ole Laursen.
30667 Licensed under the MIT license.
30668
30669 Set axis.mode to "time" to enable. See the section "Time series data" in
30670 API.txt for details.
30671
30672 */
30673
30674 (function($) {
30675
30676 var options = {
30677 xaxis: {
30678 timezone: null, // "browser" for local to the client or timezone for timezone-js
30679 timeformat: null, // format string to use
30680 twelveHourClock: false, // 12 or 24 time in time mode
30681 monthNames: null // list of names of months
30682 }
30683 };
30684
30685 // round to nearby lower multiple of base
30686
30687 function floorInBase(n, base) {
30688 return base * Math.floor(n / base);
30689 }
30690
30691 // Returns a string with the date d formatted according to fmt.
30692 // A subset of the Open Group's strftime format is supported.
30693
30694 function formatDate(d, fmt, monthNames, dayNames) {
30695
30696 if (typeof d.strftime == "function") {
30697 return d.strftime(fmt);
30698 }
30699
30700 var leftPad = function(n, pad) {
30701 n = "" + n;
30702 pad = "" + (pad == null ? "0" : pad);
30703 return n.length == 1 ? pad + n : n;
30704 };
30705
30706 var r = [];
30707 var escape = false;
30708 var hours = d.getHours();
30709 var isAM = hours < 12;
30710
30711 if (monthNames == null) {
30712 monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
30713 }
30714
30715 if (dayNames == null) {
30716 dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
30717 }
30718
30719 var hours12;
30720
30721 if (hours > 12) {
30722 hours12 = hours - 12;
30723 } else if (hours == 0) {
30724 hours12 = 12;
30725 } else {
30726 hours12 = hours;
30727 }
30728
30729 for (var i = 0; i < fmt.length; ++i) {
30730
30731 var c = fmt.charAt(i);
30732
30733 if (escape) {
30734 switch (c) {
30735 case 'a': c = "" + dayNames[d.getDay()]; break;
30736 case 'b': c = "" + monthNames[d.getMonth()]; break;
30737 case 'd': c = leftPad(d.getDate()); break;
30738 case 'e': c = leftPad(d.getDate(), " "); break;
30739 case 'h': // For back-compat with 0.7; remove in 1.0
30740 case 'H': c = leftPad(hours); break;
30741 case 'I': c = leftPad(hours12); break;
30742 case 'l': c = leftPad(hours12, " "); break;
30743 case 'm': c = leftPad(d.getMonth() + 1); break;
30744 case 'M': c = leftPad(d.getMinutes()); break;
30745 // quarters not in Open Group's strftime specification
30746 case 'q':
30747 c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
30748 case 'S': c = leftPad(d.getSeconds()); break;
30749 case 'y': c = leftPad(d.getFullYear() % 100); break;
30750 case 'Y': c = "" + d.getFullYear(); break;
30751 case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
30752 case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
30753 case 'w': c = "" + d.getDay(); break;
30754 }
30755 r.push(c);
30756 escape = false;
30757 } else {
30758 if (c == "%") {
30759 escape = true;
30760 } else {
30761 r.push(c);
30762 }
30763 }
30764 }
30765
30766 return r.join("");
30767 }
30768
30769 // To have a consistent view of time-based data independent of which time
30770 // zone the client happens to be in we need a date-like object independent
30771 // of time zones. This is done through a wrapper that only calls the UTC
30772 // versions of the accessor methods.
30773
30774 function makeUtcWrapper(d) {
30775
30776 function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
30777 sourceObj[sourceMethod] = function() {
30778 return targetObj[targetMethod].apply(targetObj, arguments);
30779 };
30780 };
30781
30782 var utc = {
30783 date: d
30784 };
30785
30786 // support strftime, if found
30787
30788 if (d.strftime != undefined) {
30789 addProxyMethod(utc, "strftime", d, "strftime");
30790 }
30791
30792 addProxyMethod(utc, "getTime", d, "getTime");
30793 addProxyMethod(utc, "setTime", d, "setTime");
30794
30795 var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
30796
30797 for (var p = 0; p < props.length; p++) {
30798 addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
30799 addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
30800 }
30801
30802 return utc;
30803 };
30804
30805 // select time zone strategy. This returns a date-like object tied to the
30806 // desired timezone
30807
30808 function dateGenerator(ts, opts) {
30809 if (opts.timezone == "browser") {
30810 return new Date(ts);
30811 } else if (!opts.timezone || opts.timezone == "utc") {
30812 return makeUtcWrapper(new Date(ts));
30813 } else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
30814 var d = new timezoneJS.Date();
30815 // timezone-js is fickle, so be sure to set the time zone before
30816 // setting the time.
30817 d.setTimezone(opts.timezone);
30818 d.setTime(ts);
30819 return d;
30820 } else {
30821 return makeUtcWrapper(new Date(ts));
30822 }
30823 }
30824
30825 // map of app. size of time units in milliseconds
30826
30827 var timeUnitSize = {
30828 "second": 1000,
30829 "minute": 60 * 1000,
30830 "hour": 60 * 60 * 1000,
30831 "day": 24 * 60 * 60 * 1000,
30832 "month": 30 * 24 * 60 * 60 * 1000,
30833 "quarter": 3 * 30 * 24 * 60 * 60 * 1000,
30834 "year": 365.2425 * 24 * 60 * 60 * 1000
30835 };
30836
30837 // the allowed tick sizes, after 1 year we use
30838 // an integer algorithm
30839
30840 var baseSpec = [
30841 [1, "second"], [2, "second"], [5, "second"], [10, "second"],
30842 [30, "second"],
30843 [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
30844 [30, "minute"],
30845 [1, "hour"], [2, "hour"], [4, "hour"],
30846 [8, "hour"], [12, "hour"],
30847 [1, "day"], [2, "day"], [3, "day"],
30848 [0.25, "month"], [0.5, "month"], [1, "month"],
30849 [2, "month"]
30850 ];
30851
30852 // we don't know which variant(s) we'll need yet, but generating both is
30853 // cheap
30854
30855 var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
30856 [1, "year"]]);
30857 var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
30858 [1, "year"]]);
30859
30860 function init(plot) {
30861 plot.hooks.processOptions.push(function (plot, options) {
30862 $.each(plot.getAxes(), function(axisName, axis) {
30863
30864 var opts = axis.options;
30865
30866 if (opts.mode == "time") {
30867 axis.tickGenerator = function(axis) {
30868
30869 var ticks = [];
30870 var d = dateGenerator(axis.min, opts);
30871 var minSize = 0;
30872
30873 // make quarter use a possibility if quarters are
30874 // mentioned in either of these options
30875
30876 var spec = (opts.tickSize && opts.tickSize[1] ===
30877 "quarter") ||
30878 (opts.minTickSize && opts.minTickSize[1] ===
30879 "quarter") ? specQuarters : specMonths;
30880
30881 if (opts.minTickSize != null) {
30882 if (typeof opts.tickSize == "number") {
30883 minSize = opts.tickSize;
30884 } else {
30885 minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
30886 }
30887 }
30888
30889 for (var i = 0; i < spec.length - 1; ++i) {
30890 if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
30891 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
30892 && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
30893 break;
30894 }
30895 }
30896
30897 var size = spec[i][0];
30898 var unit = spec[i][1];
30899
30900 // special-case the possibility of several years
30901
30902 if (unit == "year") {
30903
30904 // if given a minTickSize in years, just use it,
30905 // ensuring that it's an integer
30906
30907 if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
30908 size = Math.floor(opts.minTickSize[0]);
30909 } else {
30910
30911 var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
30912 var norm = (axis.delta / timeUnitSize.year) / magn;
30913
30914 if (norm < 1.5) {
30915 size = 1;
30916 } else if (norm < 3) {
30917 size = 2;
30918 } else if (norm < 7.5) {
30919 size = 5;
30920 } else {
30921 size = 10;
30922 }
30923
30924 size *= magn;
30925 }
30926
30927 // minimum size for years is 1
30928
30929 if (size < 1) {
30930 size = 1;
30931 }
30932 }
30933
30934 axis.tickSize = opts.tickSize || [size, unit];
30935 var tickSize = axis.tickSize[0];
30936 unit = axis.tickSize[1];
30937
30938 var step = tickSize * timeUnitSize[unit];
30939
30940 if (unit == "second") {
30941 d.setSeconds(floorInBase(d.getSeconds(), tickSize));
30942 } else if (unit == "minute") {
30943 d.setMinutes(floorInBase(d.getMinutes(), tickSize));
30944 } else if (unit == "hour") {
30945 d.setHours(floorInBase(d.getHours(), tickSize));
30946 } else if (unit == "month") {
30947 d.setMonth(floorInBase(d.getMonth(), tickSize));
30948 } else if (unit == "quarter") {
30949 d.setMonth(3 * floorInBase(d.getMonth() / 3,
30950 tickSize));
30951 } else if (unit == "year") {
30952 d.setFullYear(floorInBase(d.getFullYear(), tickSize));
30953 }
30954
30955 // reset smaller components
30956
30957 d.setMilliseconds(0);
30958
30959 if (step >= timeUnitSize.minute) {
30960 d.setSeconds(0);
30961 }
30962 if (step >= timeUnitSize.hour) {
30963 d.setMinutes(0);
30964 }
30965 if (step >= timeUnitSize.day) {
30966 d.setHours(0);
30967 }
30968 if (step >= timeUnitSize.day * 4) {
30969 d.setDate(1);
30970 }
30971 if (step >= timeUnitSize.month * 2) {
30972 d.setMonth(floorInBase(d.getMonth(), 3));
30973 }
30974 if (step >= timeUnitSize.quarter * 2) {
30975 d.setMonth(floorInBase(d.getMonth(), 6));
30976 }
30977 if (step >= timeUnitSize.year) {
30978 d.setMonth(0);
30979 }
30980
30981 var carry = 0;
30982 var v = Number.NaN;
30983 var prev;
30984
30985 do {
30986
30987 prev = v;
30988 v = d.getTime();
30989 ticks.push(v);
30990
30991 if (unit == "month" || unit == "quarter") {
30992 if (tickSize < 1) {
30993
30994 // a bit complicated - we'll divide the
30995 // month/quarter up but we need to take
30996 // care of fractions so we don't end up in
30997 // the middle of a day
30998
30999 d.setDate(1);
31000 var start = d.getTime();
31001 d.setMonth(d.getMonth() +
31002 (unit == "quarter" ? 3 : 1));
31003 var end = d.getTime();
31004 d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
31005 carry = d.getHours();
31006 d.setHours(0);
31007 } else {
31008 d.setMonth(d.getMonth() +
31009 tickSize * (unit == "quarter" ? 3 : 1));
31010 }
31011 } else if (unit == "year") {
31012 d.setFullYear(d.getFullYear() + tickSize);
31013 } else {
31014 d.setTime(v + step);
31015 }
31016 } while (v < axis.max && v != prev);
31017
31018 return ticks;
31019 };
31020
31021 axis.tickFormatter = function (v, axis) {
31022
31023 var d = dateGenerator(v, axis.options);
31024
31025 // first check global format
31026
31027 if (opts.timeformat != null) {
31028 return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
31029 }
31030
31031 // possibly use quarters if quarters are mentioned in
31032 // any of these places
31033
31034 var useQuarters = (axis.options.tickSize &&
31035 axis.options.tickSize[1] == "quarter") ||
31036 (axis.options.minTickSize &&
31037 axis.options.minTickSize[1] == "quarter");
31038
31039 var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
31040 var span = axis.max - axis.min;
31041 var suffix = (opts.twelveHourClock) ? " %p" : "";
31042 var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
31043 var fmt;
31044
31045 if (t < timeUnitSize.minute) {
31046 fmt = hourCode + ":%M:%S" + suffix;
31047 } else if (t < timeUnitSize.day) {
31048 if (span < 2 * timeUnitSize.day) {
31049 fmt = hourCode + ":%M" + suffix;
31050 } else {
31051 fmt = "%b %d " + hourCode + ":%M" + suffix;
31052 }
31053 } else if (t < timeUnitSize.month) {
31054 fmt = "%b %d";
31055 } else if ((useQuarters && t < timeUnitSize.quarter) ||
31056 (!useQuarters && t < timeUnitSize.year)) {
31057 if (span < timeUnitSize.year) {
31058 fmt = "%b";
31059 } else {
31060 fmt = "%b %Y";
31061 }
31062 } else if (useQuarters && t < timeUnitSize.year) {
31063 if (span < timeUnitSize.year) {
31064 fmt = "Q%q";
31065 } else {
31066 fmt = "Q%q %Y";
31067 }
31068 } else {
31069 fmt = "%Y";
31070 }
31071
31072 var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
31073
31074 return rt;
31075 };
31076 }
31077 });
31078 });
31079 }
31080
31081 $.plot.plugins.push({
31082 init: init,
31083 options: options,
31084 name: 'time',
31085 version: '1.0'
31086 });
31087
31088 // Time-axis support used to be in Flot core, which exposed the
31089 // formatDate function on the plot object. Various plugins depend
31090 // on the function, so we need to re-expose it here.
31091
31092 $.plot.formatDate = formatDate;
31093 $.plot.dateGenerator = dateGenerator;
31094
31095 })(jQuery);
31096 /*
31097 * jquery.flot.tooltip
31098 *
31099 * description: easy-to-use tooltips for Flot charts
31100 * version: 0.6.7
31101 * author: Krzysztof Urbas @krzysu [myviews.pl]
31102 * website: https://github.com/krzysu/flot.tooltip
31103 *
31104 * build on 2014-03-26
31105 * released under MIT License, 2012
31106 */
31107 // IE8 polyfill for Array.indexOf
31108 if (!Array.prototype.indexOf) {
31109 Array.prototype.indexOf = function (searchElement, fromIndex) {
31110 if ( this === undefined || this === null ) {
31111 throw new TypeError( '"this" is null or not defined' );
31112 }
31113 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
31114 fromIndex = +fromIndex || 0;
31115 if (Math.abs(fromIndex) === Infinity) {
31116 fromIndex = 0;
31117 }
31118 if (fromIndex < 0) {
31119 fromIndex += length;
31120 if (fromIndex < 0) {
31121 fromIndex = 0;
31122 }
31123 }
31124
31125 for (;fromIndex < length; fromIndex++) {
31126 if (this[fromIndex] === searchElement) {
31127 return fromIndex;
31128 }
31129 }
31130
31131 return -1;
31132 };
31133 }
31134
31135 (function ($) {
31136
31137 // plugin options, default values
31138 var defaultOptions = {
31139 tooltip: false,
31140 tooltipOpts: {
31141 content: "%s | X: %x | Y: %y",
31142 // allowed templates are:
31143 // %s -> series label,
31144 // %lx -> x axis label (requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels),
31145 // %ly -> y axis label (requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels),
31146 // %x -> X value,
31147 // %y -> Y value,
31148 // %x.2 -> precision of X value,
31149 // %p -> percent
31150 xDateFormat: null,
31151 yDateFormat: null,
31152 monthNames: null,
31153 dayNames: null,
31154 shifts: {
31155 x: 10,
31156 y: 20
31157 },
31158 defaultTheme: true,
31159
31160 // callbacks
31161 onHover: function(flotItem, $tooltipEl) {}
31162 }
31163 };
31164
31165 // object
31166 var FlotTooltip = function(plot) {
31167
31168 // variables
31169 this.tipPosition = {x: 0, y: 0};
31170
31171 this.init(plot);
31172 };
31173
31174 // main plugin function
31175 FlotTooltip.prototype.init = function(plot) {
31176
31177 var that = this;
31178
31179 // detect other flot plugins
31180 var plotPluginsLength = $.plot.plugins.length;
31181 this.plotPlugins = [];
31182
31183 if (plotPluginsLength) {
31184 for (var p = 0; p < plotPluginsLength; p++) {
31185 this.plotPlugins.push($.plot.plugins[p].name);
31186 }
31187 }
31188
31189 plot.hooks.bindEvents.push(function (plot, eventHolder) {
31190
31191 // get plot options
31192 that.plotOptions = plot.getOptions();
31193
31194 // if not enabled return
31195 if (that.plotOptions.tooltip === false || typeof that.plotOptions.tooltip === 'undefined') return;
31196
31197 // shortcut to access tooltip options
31198 that.tooltipOptions = that.plotOptions.tooltipOpts;
31199
31200 // create tooltip DOM element
31201 var $tip = that.getDomElement();
31202
31203 // bind event
31204 $( plot.getPlaceholder() ).bind("plothover", plothover);
31205
31206 $(eventHolder).bind('mousemove', mouseMove);
31207 });
31208
31209 plot.hooks.shutdown.push(function (plot, eventHolder){
31210 $(plot.getPlaceholder()).unbind("plothover", plothover);
31211 $(eventHolder).unbind("mousemove", mouseMove);
31212 });
31213
31214 function mouseMove(e){
31215 var pos = {};
31216 pos.x = e.pageX;
31217 pos.y = e.pageY;
31218 that.updateTooltipPosition(pos);
31219 }
31220
31221 function plothover(event, pos, item) {
31222 var $tip = that.getDomElement();
31223 if (item) {
31224 var tipText;
31225
31226 // convert tooltip content template to real tipText
31227 tipText = that.stringFormat(that.tooltipOptions.content, item);
31228
31229 $tip.html( tipText );
31230 that.updateTooltipPosition({ x: pos.pageX, y: pos.pageY });
31231 $tip.css({
31232 left: that.tipPosition.x + that.tooltipOptions.shifts.x,
31233 top: that.tipPosition.y + that.tooltipOptions.shifts.y
31234 })
31235 .show();
31236
31237 // run callback
31238 if(typeof that.tooltipOptions.onHover === 'function') {
31239 that.tooltipOptions.onHover(item, $tip);
31240 }
31241 }
31242 else {
31243 $tip.hide().html('');
31244 }
31245 }
31246 };
31247
31248 /**
31249 * get or create tooltip DOM element
31250 * @return jQuery object
31251 */
31252 FlotTooltip.prototype.getDomElement = function() {
31253 var $tip;
31254
31255 if( $('#flotTip').length > 0 ){
31256 $tip = $('#flotTip');
31257 }
31258 else {
31259 $tip = $('<div />').attr('id', 'flotTip');
31260 $tip.appendTo('body').hide().css({position: 'absolute'});
31261
31262 if(this.tooltipOptions.defaultTheme) {
31263 $tip.css({
31264 'background': '#fff',
31265 'z-index': '1040',
31266 'padding': '0.4em 0.6em',
31267 'border-radius': '0.5em',
31268 'font-size': '0.8em',
31269 'border': '1px solid #111',
31270 'display': 'none',
31271 'white-space': 'nowrap'
31272 });
31273 }
31274 }
31275
31276 return $tip;
31277 };
31278
31279 // as the name says
31280 FlotTooltip.prototype.updateTooltipPosition = function(pos) {
31281 var totalTipWidth = $("#flotTip").outerWidth() + this.tooltipOptions.shifts.x;
31282 var totalTipHeight = $("#flotTip").outerHeight() + this.tooltipOptions.shifts.y;
31283 if ((pos.x - $(window).scrollLeft()) > ($(window).innerWidth() - totalTipWidth)) {
31284 pos.x -= totalTipWidth;
31285 }
31286 if ((pos.y - $(window).scrollTop()) > ($(window).innerHeight() - totalTipHeight)) {
31287 pos.y -= totalTipHeight;
31288 }
31289 this.tipPosition.x = pos.x;
31290 this.tipPosition.y = pos.y;
31291 };
31292
31293 /**
31294 * core function, create tooltip content
31295 * @param {string} content - template with tooltip content
31296 * @param {object} item - Flot item
31297 * @return {string} real tooltip content for current item
31298 */
31299 FlotTooltip.prototype.stringFormat = function(content, item) {
31300
31301 var percentPattern = /%p\.{0,1}(\d{0,})/;
31302 var seriesPattern = /%s/;
31303 var xLabelPattern = /%lx/; // requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels, will be ignored if plugin isn't loaded
31304 var yLabelPattern = /%ly/; // requires flot-axislabels plugin https://github.com/markrcote/flot-axislabels, will be ignored if plugin isn't loaded
31305 var xPattern = /%x\.{0,1}(\d{0,})/;
31306 var yPattern = /%y\.{0,1}(\d{0,})/;
31307 var xPatternWithoutPrecision = "%x";
31308 var yPatternWithoutPrecision = "%y";
31309
31310 var x, y;
31311
31312 // for threshold plugin we need to read data from different place
31313 if (typeof item.series.threshold !== "undefined") {
31314 x = item.datapoint[0];
31315 y = item.datapoint[1];
31316 } else {
31317 x = item.series.data[item.dataIndex][0];
31318 y = item.series.data[item.dataIndex][1];
31319 }
31320
31321 // I think this is only in case of threshold plugin
31322 if (item.series.label === null && item.series.originSeries) {
31323 item.series.label = item.series.originSeries.label;
31324 }
31325
31326 // if it is a function callback get the content string
31327 if( typeof(content) === 'function' ) {
31328 content = content(item.series.label, x, y, item);
31329 }
31330
31331 // percent match for pie charts
31332 if( typeof (item.series.percent) !== 'undefined' ) {
31333 content = this.adjustValPrecision(percentPattern, content, item.series.percent);
31334 }
31335
31336 // series match
31337 if( typeof(item.series.label) !== 'undefined' ) {
31338 content = content.replace(seriesPattern, item.series.label);
31339 }
31340 else {
31341 //remove %s if label is undefined
31342 content = content.replace(seriesPattern, "");
31343 }
31344
31345 // x axis label match
31346 if( this.hasAxisLabel('xaxis', item) ) {
31347 content = content.replace(xLabelPattern, item.series.xaxis.options.axisLabel);
31348 }
31349 else {
31350 //remove %lx if axis label is undefined or axislabels plugin not present
31351 content = content.replace(xLabelPattern, "");
31352 }
31353
31354 // y axis label match
31355 if( this.hasAxisLabel('yaxis', item) ) {
31356 content = content.replace(yLabelPattern, item.series.yaxis.options.axisLabel);
31357 }
31358 else {
31359 //remove %ly if axis label is undefined or axislabels plugin not present
31360 content = content.replace(yLabelPattern, "");
31361 }
31362
31363 // time mode axes with custom dateFormat
31364 if(this.isTimeMode('xaxis', item) && this.isXDateFormat(item)) {
31365 content = content.replace(xPattern, this.timestampToDate(x, this.tooltipOptions.xDateFormat));
31366 }
31367
31368 if(this.isTimeMode('yaxis', item) && this.isYDateFormat(item)) {
31369 content = content.replace(yPattern, this.timestampToDate(y, this.tooltipOptions.yDateFormat));
31370 }
31371
31372 // set precision if defined
31373 if(typeof x === 'number') {
31374 content = this.adjustValPrecision(xPattern, content, x);
31375 }
31376 if(typeof y === 'number') {
31377 content = this.adjustValPrecision(yPattern, content, y);
31378 }
31379
31380 // change x from number to given label, if given
31381 if(typeof item.series.xaxis.ticks !== 'undefined') {
31382
31383 var ticks;
31384 if(this.hasRotatedXAxisTicks(item)) {
31385 // xaxis.ticks will be an empty array if tickRotor is being used, but the values are available in rotatedTicks
31386 ticks = 'rotatedTicks';
31387 }
31388 else {
31389 ticks = 'ticks';
31390 }
31391
31392 // see https://github.com/krzysu/flot.tooltip/issues/65
31393 var tickIndex = item.dataIndex + item.seriesIndex;
31394
31395 if(item.series.xaxis[ticks].length > tickIndex && !this.isTimeMode('xaxis', item))
31396 content = content.replace(xPattern, item.series.xaxis[ticks][tickIndex].label);
31397 }
31398
31399 // change y from number to given label, if given
31400 if(typeof item.series.yaxis.ticks !== 'undefined') {
31401 for (var index in item.series.yaxis.ticks) {
31402 if (item.series.yaxis.ticks.hasOwnProperty(index)) {
31403 var value = (this.isCategoriesMode('yaxis', item)) ? item.series.yaxis.ticks[index].label : item.series.yaxis.ticks[index].v;
31404 if (value === y) {
31405 content = content.replace(yPattern, item.series.yaxis.ticks[index].label);
31406 }
31407 }
31408 }
31409 }
31410
31411 // if no value customization, use tickFormatter by default
31412 if(typeof item.series.xaxis.tickFormatter !== 'undefined') {
31413 //escape dollar
31414 content = content.replace(xPatternWithoutPrecision, item.series.xaxis.tickFormatter(x, item.series.xaxis).replace(/\$/g, '$$'));
31415 }
31416 if(typeof item.series.yaxis.tickFormatter !== 'undefined') {
31417 //escape dollar
31418 content = content.replace(yPatternWithoutPrecision, item.series.yaxis.tickFormatter(y, item.series.yaxis).replace(/\$/g, '$$'));
31419 }
31420
31421 return content;
31422 };
31423
31424 // helpers just for readability
31425 FlotTooltip.prototype.isTimeMode = function(axisName, item) {
31426 return (typeof item.series[axisName].options.mode !== 'undefined' && item.series[axisName].options.mode === 'time');
31427 };
31428
31429 FlotTooltip.prototype.isXDateFormat = function(item) {
31430 return (typeof this.tooltipOptions.xDateFormat !== 'undefined' && this.tooltipOptions.xDateFormat !== null);
31431 };
31432
31433 FlotTooltip.prototype.isYDateFormat = function(item) {
31434 return (typeof this.tooltipOptions.yDateFormat !== 'undefined' && this.tooltipOptions.yDateFormat !== null);
31435 };
31436
31437 FlotTooltip.prototype.isCategoriesMode = function(axisName, item) {
31438 return (typeof item.series[axisName].options.mode !== 'undefined' && item.series[axisName].options.mode === 'categories');
31439 };
31440
31441 //
31442 FlotTooltip.prototype.timestampToDate = function(tmst, dateFormat) {
31443 var theDate = new Date(tmst*1);
31444 return $.plot.formatDate(theDate, dateFormat, this.tooltipOptions.monthNames, this.tooltipOptions.dayNames);
31445 };
31446
31447 //
31448 FlotTooltip.prototype.adjustValPrecision = function(pattern, content, value) {
31449
31450 var precision;
31451 var matchResult = content.match(pattern);
31452 if( matchResult !== null ) {
31453 if(RegExp.$1 !== '') {
31454 precision = RegExp.$1;
31455 value = value.toFixed(precision);
31456
31457 // only replace content if precision exists, in other case use thickformater
31458 content = content.replace(pattern, value);
31459 }
31460 }
31461 return content;
31462 };
31463
31464 // other plugins detection below
31465
31466 // check if flot-axislabels plugin (https://github.com/markrcote/flot-axislabels) is used and that an axis label is given
31467 FlotTooltip.prototype.hasAxisLabel = function(axisName, item) {
31468 return (this.plotPlugins.indexOf('axisLabels') !== -1 && typeof item.series[axisName].options.axisLabel !== 'undefined' && item.series[axisName].options.axisLabel.length > 0);
31469 };
31470
31471 // check whether flot-tickRotor, a plugin which allows rotation of X-axis ticks, is being used
31472 FlotTooltip.prototype.hasRotatedXAxisTicks = function(item) {
31473 return ($.grep($.plot.plugins, function(p){ return p.name === "tickRotor"; }).length === 1 && typeof item.series.xaxis.rotatedTicks !== 'undefined');
31474 };
31475
31476 //
31477 var init = function(plot) {
31478 new FlotTooltip(plot);
31479 };
31480
31481 // define Flot plugin
31482 $.plot.plugins.push({
31483 init: init,
31484 options: defaultOptions,
31485 name: 'tooltip',
31486 version: '0.6.7'
31487 });
31488
31489 })(jQuery);
31490 // SIMILE is not used anymore (and messes with jQuery!) so it was removed
31491 // TimeplotLoader.load(GeoTemCoLoader.urlPrefix + 'lib/', GeoTemCoLoader.loadScripts);
31492
31493 // ..but we still need (and use) the following defines, that where copied from there
31494 /* string.js */
31495 String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"");
31496 };
31497 String.prototype.startsWith=function(A){return this.length>=A.length&&this.substr(0,A.length)==A;
31498 };
31499 String.prototype.endsWith=function(A){return this.length>=A.length&&this.substr(this.length-A.length)==A;
31500 };
31501 String.substitute=function(B,D){var A="";
31502 var F=0;
31503 while(F<B.length-1){var C=B.indexOf("%",F);
31504 if(C<0||C==B.length-1){break;
31505 }else{if(C>F&&B.charAt(C-1)=="\\"){A+=B.substring(F,C-1)+"%";
31506 F=C+1;
31507 }else{var E=parseInt(B.charAt(C+1));
31508 if(isNaN(E)||E>=D.length){A+=B.substring(F,C+2);
31509 }else{A+=B.substring(F,C)+D[E].toString();
31510 }F=C+2;
31511 }}}if(F<B.length){A+=B.substring(F);
31512 }return A;
31513 };
31514
31515 /* date-time.js */
31516 SimileAjax=new Object();
31517 SimileAjax.DateTime=new Object();
31518 SimileAjax.DateTime.MILLISECOND=0;
31519 SimileAjax.DateTime.SECOND=1;
31520 SimileAjax.DateTime.MINUTE=2;
31521 SimileAjax.DateTime.HOUR=3;
31522 SimileAjax.DateTime.DAY=4;
31523 SimileAjax.DateTime.WEEK=5;
31524 SimileAjax.DateTime.MONTH=6;
31525 SimileAjax.DateTime.YEAR=7;
31526 SimileAjax.DateTime.DECADE=8;
31527 SimileAjax.DateTime.CENTURY=9;
31528 SimileAjax.DateTime.MILLENNIUM=10;
31529 SimileAjax.DateTime.EPOCH=-1;
31530 SimileAjax.DateTime.ERA=-2;
31531
31532 SimileAjax.includeCssFile = function(doc, url) {
31533 var link = doc.createElement("link");
31534 link.setAttribute("rel", "stylesheet");
31535 link.setAttribute("type", "text/css");
31536 link.setAttribute("href", url);
31537 doc.getElementsByTagName("head")[0].appendChild(link);
31538 };
31539 /*
31540 * Tooltips.js
31541 *
31542 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
31543 *
31544 * This library is free software; you can redistribute it and/or
31545 * modify it under the terms of the GNU Lesser General Public
31546 * License as published by the Free Software Foundation; either
31547 * version 3 of the License, or (at your option) any later version.
31548 *
31549 * This library is distributed in the hope that it will be useful,
31550 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31551 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31552 * Lesser General Public License for more details.
31553 *
31554 * You should have received a copy of the GNU Lesser General Public
31555 * License along with this library; if not, write to the Free Software
31556 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
31557 * MA 02110-1301 USA
31558 */
31559
31560 /**
31561 * Tooltips JSON
31562 * GeoTemCo tooltips definition file
31563 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
31564 * @release 1.0
31565 * @release date: 2012-07-27
31566 * @version date: 2012-07-27
31567 */
31568 var Tooltips = {
31569 "en" : {
31570 "locationType" : "Location type",
31571 "selectLocationType" : "Select location type",
31572 "mapType" : "Background map",
31573 "selectMapType" : "Select background map",
31574 "selectOverlay" : "Select layer for spatial filtering",
31575 "overlays" : "Select layer",
31576 "mapSelectorTools" : "Map selector tools",
31577 "overlaySelector" : "Selection layer",
31578 "square" : "Square selection: Mouse down for the center and mouse move to set square bounds",
31579 "circle" : "Circle selection: Mouse down for the center and mouse move to set circle radius",
31580 "polygon" : "Polygon selection: Click to add vertex and double click to complete the polygon",
31581 "country" : "Country selection: Click inside the political borders of a country",
31582 "singleEntry" : "Only 1 entry available",
31583 "resultsLocation" : "with location information",
31584 "home" : "Reset map to initial view",
31585 "zoomIn" : "Zoom in",
31586 "zoomOut" : "Zoom out",
31587 "zoomSlider" : "Zoom slider",
31588 "dragSelection" : "Drag&Drop shape",
31589 "zoomSelection" : "Zoom into selection",
31590 "clearSelection" : "Clear selection",
31591 "contemporaryMap" : "Contemporary Map",
31592 "activateGeoLocation" : "Show my location",
31593 "deactivateGeoLocation" : "Hide my location",
31594 "mapOf" : "Map of",
31595 "close" : "Close",
31596 "genericBinning" : "delaunay",
31597 "squareBinning" : "square",
31598 "hexagonalBinning" : "hexagonal",
31599 "triangularBinning" : "triangular",
31600 "noBinning" : "none",
31601 "selectBinningType" : "Select aggregation type",
31602 "binningType" : "Aggregation type",
31603 "binningTooltip" : "Select the aggregation type for the data sources",
31604 "results" : "results",
31605 "result" : "result",
31606 "timeType" : "Time type",
31607 "timeUnit" : "Time unit:",
31608 "selectTimeType" : "Select time type",
31609 "timeAnimation" : "Animation",
31610 "resultsTime" : "with time information",
31611 "animationDisabled" : "Animation control (disabled)",
31612 "animationPlay" : "Animate selected time range",
31613 "animationPause" : "Pause animation",
31614 "leftHandle" : "Drag&Drop left border",
31615 "rightHandle" : "Drag&Drop right border",
31616 "dragTimeRange" : "Drag&Drop time range",
31617 "connectionsOn" : "Switch on time-dependent connections between map circles",
31618 "connectionsOff" : "Switch off time-dependent connections",
31619 "timeFeather" : "Adjust time range feather to smoothen map animations",
31620 "allResults" : "all",
31621 "pageInfo" : "Page PAGE_ID of PAGES_ID",
31622 "resultsInfo" : "RESULTS_FROM_ID-RESULTS_TO_ID of RESULTS_ID Results",
31623 "otherResults" : "others",
31624 "mapAggregation" : "Aggregation",
31625 "aggregation" : "Circle aggregation",
31626 "noAggregation" : "No circle aggregation",
31627 "showBoxTitle" : "Boundingbox",
31628 "showBbox" : "Shows given Boundingbox extension",
31629 "hideBbox" : "Hides given Boundingbox extension",
31630 "spaceHelp" : "A point on the map corresponds to one or more objects from the result list. ",
31631 "timeHelp" : "On the timeline are the search results sorted by year. You can choose different time-based categories as basis for the representation.",
31632 "selectTablePageItemsHelp" : "Click to select all rows of this page",
31633 "deselectTablePageItemsHelp" : "Click to deselect all rows of this page",
31634 "selectAllTableItemsHelp" : "Click to select all rows of the table",
31635 "deselectAllTableItemsHelp" : "Click to deselect all rows of the table",
31636 "filter" : "Filter",
31637 "filterSelectedItemsHelp" : "Filter the selected items",
31638 "inverseFilterSelectedItemsHelp" : "Apply an inverse filter on the selected items removing them from the views",
31639 "undoFilterSelection" : "Undo the last filter / inverse filter",
31640 "cancelSelection" : "Discard the current selection (all items appear as deselected)",
31641 "showSelectedHelp" : "Show only elements within the selection",
31642 "selectByTextHelp" : "Select elements that contain the given text",
31643 "showAllElementsHelp" : "Show all elements",
31644 "paginationFirsPageHelp" : "Show first page",
31645 "paginationPreviousPageHelp" : "Show previous page",
31646 "paginationNextPageHelp" : "Show next page",
31647 "paginationLastPageHelp" : "Show last page",
31648 "sortAZHelp" : "Sort table elements ascending according this column",
31649 "sortZAHelp" : "Sort table elements descending according this column",
31650 "paginationDropdownHelp" : "Select number of elements per page",
31651 "selectTimeUnit" : "Select Time Unit",
31652 "valueScale" : "Value Scale",
31653 "linearPlot" : "Linear Value Scale",
31654 "logarithmicPlot" : "Logarithmic Value Scale",
31655 "playButton" : "Animate Selected Range",
31656 "pauseButton" : "Pause Animation",
31657 "createNewFromSelectedHelp" : "Create new dataset from selected values",
31658 "removeDatasetHelp" : "Remove this dataset",
31659 "exportDatasetHelp" : "Export this dataset to a KML file",
31660 "invertSelectionHelp" : "Invert the current selection",
31661 "colorShapeDatasetHelp" : "change color or shape of dataset",
31662 "lockMap" : "lock the map in this state"
31663 },
31664 "de" : {
31665 "locationType" : "Ortsfacette",
31666 "selectLocationType" : "W&auml;hle Ortsfacette",
31667 "mapType" : "Kartentyp",
31668 "selectMapType" : "W&auml;hle Kartentyp",
31669 "selectOverlay" : "Kartenauswahl f&uuml;r r&auml;mliches filtern",
31670 "overlays" : "W&auml;hle layer",
31671 "mapSelectorTools" : "Bereichsauswahl",
31672 "overlaySelector" : "Selection layer",
31673 "square" : "Quadratauswahl: Maus ziehen und loslassen um Mittelpunkt und Seitenl&auml;nge des Quadrats zu bestimmen",
31674 "circle" : "Kreisauswahl: Maus ziehen und loslassen um Mittelpunkt und Radius des Kreises zu bestimmen",
31675 "polygon" : "Polygonauswahl: Mausklick zum Hinzuf&uuml;gen eines Eckpunktes, Doppelklick zum Fertigstellen",
31676 "country" : "Landauswahl: Mausklick innerhalb politischer Grenze eines Landes",
31677 "singleEntry" : "Nur 1 Eintrag vorhanden",
31678 "resultsLocation" : "mit Geoinformation",
31679 "home" : "Zur&uuml;cksetzen zur initialen Sicht",
31680 "zoomIn" : "Vergr&ouml;&szlig;ern",
31681 "zoomOut" : "Verkleinern",
31682 "zoomSlider" : "Zoomregler",
31683 "dragSelection" : "Verschiebe Auswahl",
31684 "zoomSelection" : "Vergr&ouml;&szlig;ere Auswahl",
31685 "clearSelection" : "Entferne Auswahlbereich",
31686 "contemporaryMap" : "Aktuelle Weltkarte",
31687 "activateGeoLocation" : "Meinen Standort anzeigen",
31688 "deactivateGeoLocation" : "Meinen Standort ausblenden",
31689 "mapOf" : "Karte von",
31690 "close" : "Schliessen",
31691 "genericBinning" : "Generisch",
31692 "squareBinning" : "Quadrate",
31693 "hexagonalBinning" : "Hexagone",
31694 "triangularBinning" : "Dreiecke",
31695 "noBinning" : "Keine Bins",
31696 "selectBinningType" : "W&auml;hle Binningart",
31697 "binningTooltip" : "W&aunl;hle die Binninart f&uuml;r die Datenquellen",
31698 "binningType" : "Binningart",
31699 "results" : "Resultate",
31700 "result" : "Resultat",
31701 "timeType" : "Zeitfacette",
31702 "timeUnit" : "Zeiteinheit",
31703 "selectTimeType" : "W&auml;hle Zeitfacette",
31704 "timeAnimation" : "Animation",
31705 "resultsTime" : "mit Zeitinformation",
31706 "animationDisabled" : "Animationswerkzeug (deaktiviert)",
31707 "animationPlay" : "Animiere ausgew&auml;hlten Zeitbereich",
31708 "animationPause" : "Animation anhalten",
31709 "leftHandle" : "Verschiebe linke Grenze",
31710 "rightHandle" : "Verschiebe rechte Grenze",
31711 "dragTimeRange" : "Verschiebe Zeitbereich",
31712 "connectionsOn" : "Aktiviere zeitabhängige Verbindungen zwischen Kreisen auf der Karte",
31713 "connectionsOff" : "Deaktiviere zeitabhängige Verbindungen",
31714 "timeFeather" : "Ver&auml;ndere Zeitbereichs&uuml;berg&auml;nge zum Gl&auml;tten der Animation",
31715 "pageInfo" : "Seite PAGE_ID von PAGES_ID",
31716 "resultsInfo" : "RESULTS_FROM_ID-RESULTS_TO_ID von RESULTS_ID Ergebnissen",
31717 "allResults" : "alle",
31718 "otherResults" : "sonstige",
31719 "mapAggregation" : "Aggregation",
31720 "aggregation" : "Kreise aggregiert",
31721 "noAggregation" : "Kreise nicht aggregiert",
31722 "showBbox" : "Geografische Ausdehnung anzeigen",
31723 "hideBbox" : "Geografische Ausdehnung ausblenden",
31724 "spaceHelp" : "Jeder Punkt auf der Karte entspricht einem oder mehreren Objekten der Ergebnisliste. Sie k&ouml;nnen verschiedene ortsbezogene Kategorien als Grundlage f&uuml;r die Darstellung w&auml;hlen (Auswahlfeld <strong>Ortsfacette</strong>) und verschiedene Kartentypen. <br> Da es Objekte geben kann, die keine Ortsangabe in ihrer Beschreibung enthalten, ist die Menge der in der Karte dargestellten Objekte in der Regel kleiner als in der Ergebnisliste (Anzahl darstellbarer Objekte siehe rechts oben über der Karte). <br> Mit der Karte können Sie die Suchergebnisse weiter eingrenzen, indem Sie auf einen der Punkte klicken. Wählen Sie einen Ort aus und klicken Sie auf die kleine Lupe, um die Ergebnisliste so einzuschränken, dass nur noch die diesem Ort zugeordneten Objekte als Suchergebnis erscheinen. Mehr zur Karte im Benutzerhandbuch ...",
31725 "timeHelp" : "In der Zeitleiste sind die Suchergebnisse nach Jahren geordnet. Sie k&ouml;nnen verschiedene zeitbezogene Kategorien als Grundlage f&uuml;r die Darstellung w&auml;hlen (Auswahlfeld <strong>Zeitfacette</strong>). <br> Da es Objekte geben kann, die keine Zeitangabe in ihrer Beschreibung enthalten, ist die Zahl der in der Zeitleiste dargestellten Objekte in der Regel kleiner als in der Ergebnisliste. Die Angabe über darstellbare Objekte finden Sie rechts über der Zeitleiste. <br>Mit der Zeitleiste können Sie die Suchergebnisse weiter eingrenzen. Wählen Sie ein Jahr oder einen Zeitraum durch Klicken und Ziehen und klicken Sie auf die kleine Lupe. Die Ergebnisliste zeigt nur noch die Objekte in diesem Zeitraum. Mehr zur Zeitleiste im Benutzerhandbuch ...",
31726 "selectTablePageItemsHelp" : "Click to select all rows of this page",
31727 "deselectTablePageItemsHelp" : "Click to deselect all rows of this page",
31728 "selectAllTableItemsHelp" : "Click to select all rows of the table",
31729 "deselectAllTableItemsHelp" : "Click to deselect all rows of the table",
31730 "filter" : "Filter",
31731 "filterSelectedItemsHelp" : "Filter the selected items",
31732 "inverseFilterSelectedItemsHelp" : "Apply an inverse filter on the selected items removing them from the views",
31733 "undoFilterSelection" : "Undo the last filter / inverse filter",
31734 "cancelSelection" : "Discard the current selection (all items appear as deselected)",
31735 "showSelectedHelp" : "Show only elements within the selection",
31736 "selectByTextHelp" : "Select elements that contain the given text",
31737 "showAllElementsHelp" : "Show all elements",
31738 "paginationFirsPageHelp" : "Show first page",
31739 "paginationPreviousPageHelp" : "Show previous page",
31740 "paginationNextPageHelp" : "Show next page",
31741 "paginationLastPageHelp" : "Show last page",
31742 "sortAZHelp" : "Sort table elements ascending according this column",
31743 "sortZAHelp" : "Sort table elements descending according this column",
31744 "paginationDropdownHelp" : "Select number of elements per page",
31745 "selectTimeUnit" : "W&auml;hle Zeitinervalle",
31746 "valueScale" : "Value Scale",
31747 "linearPlot" : "Linear Value Scale",
31748 "logarithmicPlot" : "Logarithmic Value Scale",
31749 "playButton" : "Animate Selected Range",
31750 "pauseButton" : "Pause Animation",
31751 "createNewFromSelectedHelp" : "Erstelle neuen Datensatz aus den selektierten Eintr&auml;gen",
31752 "removeDatasetHelp" : "Diesen Datensatz entfernen",
31753 "exportDatasetHelp" : "Diesen Datensatz in KML Datei exportieren",
31754 "invertSelectionHelp" : "Jetzige Selektion umkehren",
31755 "colorShapeDatasetHelp" : "Farbe oder Form des Datensatzes ändern",
31756 "lockMap" : "Karte in diesem Zustand halten."
31757 }
31758 }
31759 /*
31760 * GeoTemConfig.js
31761 *
31762 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
31763 *
31764 * This library is free software; you can redistribute it and/or
31765 * modify it under the terms of the GNU Lesser General Public
31766 * License as published by the Free Software Foundation; either
31767 * version 3 of the License, or (at your option) any later version.
31768 *
31769 * This library is distributed in the hope that it will be useful,
31770 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31771 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31772 * Lesser General Public License for more details.
31773 *
31774 * You should have received a copy of the GNU Lesser General Public
31775 * License along with this library; if not, write to the Free Software
31776 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
31777 * MA 02110-1301 USA
31778 */
31779
31780 /**
31781 * @class GeoTemConfig
31782 * Global GeoTemCo Configuration File
31783 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
31784 * @release 1.0
31785 * @release date: 2012-07-27
31786 * @version date: 2012-07-27
31787 */
31788
31789
31790 // credits: user76888, The Digital Gabeg (http://stackoverflow.com/questions/1539367)
31791 $.fn.cleanWhitespace = function() {
31792 textNodes = this.contents().filter( function() {
31793 return (this.nodeType == 3 && !/\S/.test(this.nodeValue));
31794 }).remove();
31795 return this;
31796 };
31797
31798 GeoTemConfig = {
31799 debug : false, //show debug output (esp. regarding corrupt datasets)
31800 incompleteData : true, // show/hide data with either temporal or spatial metadata
31801 inverseFilter : true, // if inverse filtering is offered
31802 mouseWheelZoom : true, // enable/disable zoom with mouse wheel on map & timeplot
31803 language : 'en', // default language of GeoTemCo
31804 allowFilter : true, // if filtering should be allowed
31805 highlightEvents : true, // if updates after highlight events
31806 selectionEvents : true, // if updates after selection events
31807 tableExportDataset : true, // export dataset to KML
31808 allowCustomColoring : false, // if DataObjects can have an own color (useful for weighted coloring)
31809 allowUserShapeAndColorChange: false, // if the user can change the shapes and color of datasets
31810 // this turns MapConfig.useGraphics auto-on, but uses circles as default
31811 loadColorFromDataset : false, // if DataObject color should be loaded automatically (from column "color")
31812 allowColumnRenaming : true,
31813 //proxy : 'php/proxy.php?address=', //set this if a HTTP proxy shall be used (e.g. to bypass X-Domain problems)
31814 //colors for several datasets; rgb1 will be used for selected objects, rgb0 for unselected
31815 colors : [{
31816 r1 : 255,
31817 g1 : 101,
31818 b1 : 0,
31819 r0 : 253,
31820 g0 : 229,
31821 b0 : 205
31822 }, {
31823 r1 : 144,
31824 g1 : 26,
31825 b1 : 255,
31826 r0 : 230,
31827 g0 : 225,
31828 b0 : 255
31829 }, {
31830 r1 : 0,
31831 g1 : 217,
31832 b1 : 0,
31833 r0 : 213,
31834 g0 : 255,
31835 b0 : 213
31836 }, {
31837 r1 : 240,
31838 g1 : 220,
31839 b1 : 0,
31840 r0 : 247,
31841 g0 : 244,
31842 b0 : 197
31843 }]
31844
31845 }
31846
31847 GeoTemConfig.ie = false;
31848 GeoTemConfig.ie8 = false;
31849
31850 GeoTemConfig.independentMapId = 0;
31851 GeoTemConfig.independentTimeId = 0;
31852
31853 if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
31854 GeoTemConfig.ie = true;
31855 var ieversion = new Number(RegExp.$1);
31856 if (ieversion == 8) {
31857 GeoTemConfig.ie8 = true;
31858 }
31859 }
31860
31861 GeoTemConfig.getIndependentId = function(target){
31862 if( target == 'map' ){
31863 return ++GeoTemConfig.independentMapId;
31864 }
31865 if( target == 'time' ){
31866 return ++GeoTemConfig.independentTimeId;
31867 }
31868 return 0;
31869 };
31870
31871 GeoTemConfig.setHexColor = function(hex,index,fill){
31872 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
31873 if( fill ){
31874 GeoTemConfig.colors[index].r0 = parseInt(result[1], 16);
31875 GeoTemConfig.colors[index].g0 = parseInt(result[2], 16);
31876 GeoTemConfig.colors[index].b0 = parseInt(result[3], 16);
31877 }
31878 else {
31879 GeoTemConfig.colors[index].r1 = parseInt(result[1], 16);
31880 GeoTemConfig.colors[index].g1 = parseInt(result[2], 16);
31881 GeoTemConfig.colors[index].b1 = parseInt(result[3], 16);
31882 }
31883 }
31884
31885 GeoTemConfig.setRgbColor = function(r,g,b,index,fill){
31886 if( fill ){
31887 GeoTemConfig.colors[index].r0 = r;
31888 GeoTemConfig.colors[index].g0 = g;
31889 GeoTemConfig.colors[index].b0 = b;
31890 }
31891 else {
31892 GeoTemConfig.colors[index].r1 = r;
31893 GeoTemConfig.colors[index].g1 = g;
31894 GeoTemConfig.colors[index].b1 = b;
31895 }
31896 }
31897
31898 GeoTemConfig.configure = function(urlPrefix) {
31899 GeoTemConfig.urlPrefix = urlPrefix;
31900 GeoTemConfig.path = GeoTemConfig.urlPrefix + "images/";
31901 }
31902
31903 GeoTemConfig.applySettings = function(settings) {
31904 $.extend(this, settings);
31905 };
31906
31907 //Keeps track of how many colors where assigned yet.
31908 GeoTemConfig.assignedColorCount = 0;
31909 GeoTemConfig.getColor = function(id){
31910 if (typeof GeoTemConfig.datasets[id].color === "undefined"){
31911 var color;
31912
31913 while (true){
31914 if( GeoTemConfig.colors.length <= GeoTemConfig.assignedColorCount ){
31915 color = {
31916 r1 : Math.floor((Math.random()*255)+1),
31917 g1 : Math.floor((Math.random()*255)+1),
31918 b1 : Math.floor((Math.random()*255)+1),
31919 r0 : 230,
31920 g0 : 230,
31921 b0 : 230
31922 };
31923 } else
31924 color = GeoTemConfig.colors[GeoTemConfig.assignedColorCount];
31925
31926 //make sure that no other dataset has this color
31927 //TODO: one could also check that they are not too much alike
31928 var found = false;
31929 for (var i = 0; i < GeoTemConfig.datasets.length; i++){
31930 var dataset = GeoTemConfig.datasets[i];
31931
31932 if (typeof dataset.color === "undefined")
31933 continue;
31934
31935 if ( (dataset.color.r1 == color.r1) &&
31936 (dataset.color.g1 == color.g1) &&
31937 (dataset.color.b1 == color.b1) ){
31938 found = true;
31939 break;
31940 }
31941 }
31942 if (found === true){
31943 if( GeoTemConfig.colors.length <= GeoTemConfig.assignedColorCount ){
31944 //next time skip over this color
31945 GeoTemConfig.assignedColorCount++;
31946 }
31947 continue;
31948 } else {
31949 GeoTemConfig.colors.push(color);
31950 break;
31951 }
31952 }
31953 GeoTemConfig.datasets[id].color = color;
31954
31955 GeoTemConfig.assignedColorCount++;
31956 }
31957 return GeoTemConfig.datasets[id].color;
31958 };
31959
31960 GeoTemConfig.getAverageDatasetColor = function(id, objects){
31961 var c = new Object();
31962 var datasetColor = GeoTemConfig.getColor(id);
31963 c.r0 = datasetColor.r0;
31964 c.g0 = datasetColor.g0;
31965 c.b0 = datasetColor.b0;
31966 c.r1 = datasetColor.r1;
31967 c.g1 = datasetColor.g1;
31968 c.b1 = datasetColor.b1;
31969 if (!GeoTemConfig.allowCustomColoring)
31970 return c;
31971 if (objects.length == 0)
31972 return c;
31973 var avgColor = new Object();
31974 avgColor.r0 = 0;
31975 avgColor.g0 = 0;
31976 avgColor.b0 = 0;
31977 avgColor.r1 = 0;
31978 avgColor.g1 = 0;
31979 avgColor.b1 = 0;
31980
31981 $(objects).each(function(){
31982 if (this.hasColorInformation){
31983 avgColor.r0 += this.color.r0;
31984 avgColor.g0 += this.color.g0;
31985 avgColor.b0 += this.color.b0;
31986 avgColor.r1 += this.color.r1;
31987 avgColor.g1 += this.color.g1;
31988 avgColor.b1 += this.color.b1;
31989 } else {
31990 avgColor.r0 += datasetColor.r0;
31991 avgColor.g0 += datasetColor.g0;
31992 avgColor.b0 += datasetColor.b0;
31993 avgColor.r1 += datasetColor.r1;
31994 avgColor.g1 += datasetColor.g1;
31995 avgColor.b1 += datasetColor.b1;
31996 }
31997 });
31998
31999 c.r0 = Math.floor(avgColor.r0/objects.length);
32000 c.g0 = Math.floor(avgColor.g0/objects.length);
32001 c.b0 = Math.floor(avgColor.b0/objects.length);
32002 c.r1 = Math.floor(avgColor.r1/objects.length);
32003 c.g1 = Math.floor(avgColor.g1/objects.length);
32004 c.b1 = Math.floor(avgColor.b1/objects.length);
32005
32006 return c;
32007 };
32008
32009 GeoTemConfig.getString = function(field) {
32010 if ( typeof Tooltips[GeoTemConfig.language] == 'undefined') {
32011 GeoTemConfig.language = 'en';
32012 }
32013 return Tooltips[GeoTemConfig.language][field];
32014 }
32015 /**
32016 * returns the actual mouse position
32017 * @param {Event} e the mouseevent
32018 * @return the top and left position on the screen
32019 */
32020 GeoTemConfig.getMousePosition = function(e) {
32021 if (!e) {
32022 e = window.event;
32023 }
32024 var body = (window.document.compatMode && window.document.compatMode == "CSS1Compat") ? window.document.documentElement : window.document.body;
32025 return {
32026 top : e.pageY ? e.pageY : e.clientY,
32027 left : e.pageX ? e.pageX : e.clientX
32028 };
32029 }
32030 /**
32031 * returns the json object of the file from the given url
32032 * @param {String} url the url of the file to load
32033 * @return json object of given file
32034 */
32035 GeoTemConfig.getJson = function(url,asyncFunc) {
32036 var async = false;
32037 if( asyncFunc ){
32038 async = true;
32039 }
32040
32041 var data;
32042 $.ajax({
32043 url : url,
32044 async : async,
32045 dataType : 'json',
32046 success : function(json) {
32047 data = json;
32048 if (async){
32049 asyncFunc(data);
32050 }
32051 }
32052 });
32053
32054 if (async){
32055 return data;
32056 }
32057 }
32058
32059 GeoTemConfig.mergeObjects = function(set1, set2) {
32060 var inside = [];
32061 var newSet = [];
32062 for (var i = 0; i < GeoTemConfig.datasets.length; i++){
32063 inside.push([]);
32064 newSet.push([]);
32065 }
32066 for (var i = 0; i < set1.length; i++) {
32067 for (var j = 0; j < set1[i].length; j++) {
32068 inside[i][set1[i][j].index] = true;
32069 newSet[i].push(set1[i][j]);
32070 }
32071 }
32072 for (var i = 0; i < set2.length; i++) {
32073 for (var j = 0; j < set2[i].length; j++) {
32074 if (!inside[i][set2[i][j].index]) {
32075 newSet[i].push(set2[i][j]);
32076 }
32077 }
32078 }
32079 return newSet;
32080 };
32081
32082 GeoTemConfig.datasets = [];
32083
32084 GeoTemConfig.addDataset = function(newDataset){
32085 GeoTemConfig.datasets.push(newDataset);
32086 Publisher.Publish('filterData', GeoTemConfig.datasets, null);
32087 };
32088
32089 GeoTemConfig.addDatasets = function(newDatasets){
32090 $(newDatasets).each(function(){
32091 GeoTemConfig.datasets.push(this);
32092 });
32093 Publisher.Publish('filterData', GeoTemConfig.datasets, null);
32094 };
32095
32096 GeoTemConfig.removeDataset = function(index){
32097 GeoTemConfig.datasets.splice(index,1);
32098 Publisher.Publish('filterData', GeoTemConfig.datasets, null);
32099 };
32100
32101 /**
32102 * converts the csv-file into json-format
32103 *
32104 * @param {String}
32105 * text
32106 */
32107 GeoTemConfig.convertCsv = function(text){
32108 /* convert here from CSV to JSON */
32109 var json = [];
32110 /* define expected csv table headers (first line) */
32111 var expectedHeaders = new Array("Name","Address","Description","Longitude","Latitude","TimeStamp","TimeSpan:begin","TimeSpan:end","weight");
32112 /* convert csv string to array of arrays using ucsv library */
32113 var csvArray = CSV.csvToArray(text);
32114 /* get real used table headers from csv file (first line) */
32115 var usedHeaders = csvArray[0];
32116 /* loop outer array, begin with second line */
32117 for (var i = 1; i < csvArray.length; i++) {
32118 var innerArray = csvArray[i];
32119 var dataObject = new Object();
32120 var tableContent = new Object();
32121 /* exclude lines with no content */
32122 var hasContent = false;
32123 for (var j = 0; j < innerArray.length; j++) {
32124 if (typeof innerArray[j] !== "undefined"){
32125 if (typeof innerArray[j] === "string"){
32126 if (innerArray[j].length > 0)
32127 hasContent = true;
32128 } else {
32129 hasContent = true;
32130 }
32131 }
32132
32133 if (hasContent === true)
32134 break;
32135 }
32136 if (hasContent === false)
32137 continue;
32138 /* loop inner array */
32139 for (var j = 0; j < innerArray.length; j++) {
32140 /* Name */
32141 if (usedHeaders[j] == expectedHeaders[0]) {
32142 dataObject["name"] = ""+innerArray[j];
32143 tableContent["name"] = ""+innerArray[j];
32144 }
32145 /* Address */
32146 else if (usedHeaders[j] == expectedHeaders[1]) {
32147 dataObject["place"] = ""+innerArray[j];
32148 tableContent["place"] = ""+innerArray[j];
32149 }
32150 /* Description */
32151 else if (usedHeaders[j] == expectedHeaders[2]) {
32152 dataObject["description"] = ""+innerArray[j];
32153 tableContent["description"] = ""+innerArray[j];
32154 }
32155 /* TimeStamp */
32156 else if (usedHeaders[j] == expectedHeaders[5]) {
32157 dataObject["time"] = ""+innerArray[j];
32158 }
32159 /* TimeSpan:begin */
32160 else if (usedHeaders[j] == expectedHeaders[6]) {
32161 tableContent["TimeSpan:begin"] = ""+innerArray[j];
32162 }
32163 /* TimeSpan:end */
32164 else if (usedHeaders[j] == expectedHeaders[7]) {
32165 tableContent["TimeSpan:end"] = ""+innerArray[j];
32166 }
32167 /* weight */
32168 else if (usedHeaders[j] == expectedHeaders[8]) {
32169 dataObject["weight"] = ""+innerArray[j];
32170 }
32171 /* Longitude */
32172 else if (usedHeaders[j] == expectedHeaders[3]) {
32173 dataObject["lon"] = parseFloat(innerArray[j]);
32174 }
32175 /* Latitude */
32176 else if (usedHeaders[j] == expectedHeaders[4]) {
32177 dataObject["lat"] = parseFloat(innerArray[j]);
32178 }
32179 else {
32180 var header = new String(usedHeaders[j]);
32181 //remove leading and trailing Whitespace
32182 header = $.trim(header);
32183 tableContent[header] = ""+innerArray[j];
32184 }
32185 }
32186
32187 dataObject["tableContent"] = tableContent;
32188
32189 json.push(dataObject);
32190 }
32191
32192 return json;
32193 };
32194
32195 /**
32196 * returns the xml dom object of the file from the given url
32197 * @param {String} url the url of the file to load
32198 * @return xml dom object of given file
32199 */
32200 GeoTemConfig.getKml = function(url,asyncFunc) {
32201 var data;
32202 var async = false;
32203 if( asyncFunc ){
32204 async = true;
32205 }
32206 $.ajax({
32207 url : url,
32208 async : async,
32209 dataType : 'xml',
32210 success : function(xml) {
32211 if( asyncFunc ){
32212 asyncFunc(xml);
32213 }
32214 else {
32215 data = xml;
32216 }
32217 }
32218 });
32219 if( !async ){
32220 return data;
32221 }
32222 }
32223
32224 /**
32225 * returns an array of all xml dom object of the kmls
32226 * found in the zip file from the given url
32227 *
32228 * can only be used with asyncFunc (because of browser
32229 * constraints regarding arraybuffer)
32230 *
32231 * @param {String} url the url of the file to load
32232 * @return xml dom object of given file
32233 */
32234 GeoTemConfig.getKmz = function(url,asyncFunc) {
32235 var kmlDom = new Array();
32236
32237 var async = true;
32238 if( !asyncFunc ){
32239 //if no asyncFunc is given return an empty array
32240 return kmlDom;
32241 }
32242
32243 //use XMLHttpRequest as "arraybuffer" is not
32244 //supported in jQuery native $.get
32245 var req = new XMLHttpRequest();
32246 req.open("GET",url,async);
32247 req.responseType = "arraybuffer";
32248 req.onload = function() {
32249 var zip = new JSZip();
32250 zip.load(req.response, {base64:false});
32251 var kmlFiles = zip.file(new RegExp("kml$"));
32252
32253 $(kmlFiles).each(function(){
32254 var kml = this;
32255 if (kml.data != null) {
32256 kmlDom.push($.parseXML(kml.data));
32257 }
32258 });
32259
32260 asyncFunc(kmlDom);
32261 };
32262 req.send();
32263 };
32264
32265 /**
32266 * returns the JSON "object"
32267 * from the csv file from the given url
32268 * @param {String} url the url of the file to load
32269 * @return xml dom object of given file
32270 */
32271 GeoTemConfig.getCsv = function(url,asyncFunc) {
32272 var async = false;
32273 if( asyncFunc ){
32274 async = true;
32275 }
32276
32277 //use XMLHttpRequest as synchronous behaviour
32278 //is not supported in jQuery native $.get
32279 var req = new XMLHttpRequest();
32280 req.open("GET",url,async);
32281 //can only be set on asynchronous now
32282 //req.responseType = "text";
32283 var json;
32284 req.onload = function() {
32285 json = GeoTemConfig.convertCsv(req.response);
32286 if( asyncFunc )
32287 asyncFunc(json);
32288 };
32289 req.send();
32290
32291 if( !async ){
32292 return json;
32293 }
32294 };
32295
32296 /**
32297 * loads a binary file
32298 * @param {String} url of the file to load
32299 * @return binary data
32300 */
32301 GeoTemConfig.getBinary = function(url,asyncFunc) {
32302 var async = true;
32303
32304 var req = new XMLHttpRequest();
32305 req.open("GET",url,async);
32306 req.responseType = "arraybuffer";
32307
32308 var binaryData;
32309 req.onload = function() {
32310 var arrayBuffer = req.response;
32311 asyncFunc(arrayBuffer);
32312 };
32313 req.send();
32314 };
32315
32316 /**
32317 * returns a Date and a SimileAjax.DateTime granularity value for a given XML time
32318 * @param {String} xmlTime the XML time as String
32319 * @return JSON object with a Date and a SimileAjax.DateTime granularity
32320 */
32321 GeoTemConfig.getTimeData = function(xmlTime) {
32322 if (!xmlTime)
32323 return;
32324 var dateData;
32325 try {
32326 var bc = false;
32327 if (xmlTime.startsWith("-")) {
32328 bc = true;
32329 xmlTime = xmlTime.substring(1);
32330 }
32331 var timeSplit = xmlTime.split("T");
32332 var timeData = timeSplit[0].split("-");
32333 for (var i = 0; i < timeData.length; i++) {
32334 parseInt(timeData[i]);
32335 }
32336 if (bc) {
32337 timeData[0] = "-" + timeData[0];
32338 }
32339 if (timeSplit.length == 1) {
32340 dateData = timeData;
32341 } else {
32342 var dayData;
32343 if (timeSplit[1].indexOf("Z") != -1) {
32344 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("Z") - 1).split(":");
32345 } else {
32346 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("+") - 1).split(":");
32347 }
32348 for (var i = 0; i < timeData.length; i++) {
32349 parseInt(dayData[i]);
32350 }
32351 dateData = timeData.concat(dayData);
32352 }
32353 } catch (exception) {
32354 return null;
32355 }
32356 var date, granularity;
32357 if (dateData.length == 6) {
32358 granularity = SimileAjax.DateTime.SECOND;
32359 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, dateData[2], dateData[3], dateData[4], dateData[5]));
32360 } else if (dateData.length == 3) {
32361 granularity = SimileAjax.DateTime.DAY;
32362 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, dateData[2]));
32363 } else if (dateData.length == 2) {
32364 granularity = SimileAjax.DateTime.MONTH;
32365 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, 1));
32366 } else if (dateData.length == 1) {
32367 granularity = SimileAjax.DateTime.YEAR;
32368 date = new Date(Date.UTC(dateData[0], 0, 1));
32369 }
32370 if (timeData[0] && timeData[0] < 100) {
32371 date.setFullYear(timeData[0]);
32372 }
32373
32374 //check data validity;
32375 var isValidDate = true;
32376 if ( date instanceof Date ) {
32377 if ( isNaN( date.getTime() ) )
32378 isValidDate = false;
32379 } else
32380 isValidDate = false;
32381
32382 if (!isValidDate){
32383 if ((GeoTemConfig.debug)&&(typeof console !== "undefined"))
32384 console.error(xmlTime + " is no valid time format");
32385 return null;
32386 }
32387
32388 return {
32389 date : date,
32390 granularity : granularity
32391 };
32392 }
32393 /**
32394 * converts a JSON array into an array of data objects
32395 * @param {JSON} JSON a JSON array of data items
32396 * @return an array of data objects
32397 */
32398 GeoTemConfig.loadJson = function(JSON) {
32399 var mapTimeObjects = [];
32400 var runningIndex = 0;
32401 for (var i in JSON ) {
32402 try {
32403 var item = JSON[i];
32404 var index = item.index || item.id || runningIndex++;
32405 var name = item.name || "";
32406 var description = item.description || "";
32407 var tableContent = item.tableContent || [];
32408 var locations = [];
32409 if (item.location instanceof Array) {
32410 for (var j = 0; j < item.location.length; j++) {
32411 var place = item.location[j].place || "unknown";
32412 var lon = item.location[j].lon;
32413 var lat = item.location[j].lat;
32414 if ((typeof lon === "undefined" || typeof lat === "undefined" || isNaN(lon) || isNaN(lat) ) && !GeoTemConfig.incompleteData) {
32415 throw "e";
32416 }
32417 locations.push({
32418 longitude : lon,
32419 latitude : lat,
32420 place : place
32421 });
32422 }
32423 } else {
32424 var place = item.place || "unknown";
32425 var lon = item.lon;
32426 var lat = item.lat;
32427 if ((typeof lon === "undefined" || typeof lat === "undefined" || isNaN(lon) || isNaN(lat) ) && !GeoTemConfig.incompleteData) {
32428 throw "e";
32429 }
32430 locations.push({
32431 longitude : lon,
32432 latitude : lat,
32433 place : place
32434 });
32435 }
32436 var dates = [];
32437 if (item.time instanceof Array) {
32438 for (var j = 0; j < item.time.length; j++) {
32439 var time = GeoTemConfig.getTimeData(item.time[j]);
32440 if (time == null && !GeoTemConfig.incompleteData) {
32441 throw "e";
32442 }
32443 dates.push(time);
32444 }
32445 } else {
32446 var time = GeoTemConfig.getTimeData(item.time);
32447 if (time == null && !GeoTemConfig.incompleteData) {
32448 throw "e";
32449 }
32450 if (time != null) {
32451 dates.push(time);
32452 }
32453 }
32454 var weight = parseInt(item.weight) || 1;
32455 //add all "other" attributes to table data
32456 //this is a hack to allow "invalid" JSONs
32457 var specialAttributes = ["id", "name", "description", "lon", "lat", "place", "time",
32458 "tableContent", "location", "time"];
32459 for (var attribute in item){
32460 if ($.inArray(attribute, specialAttributes) == -1){
32461 tableContent[attribute] = item[attribute];
32462 }
32463 }
32464
32465 var mapTimeObject = new DataObject(name, description, locations, dates, weight, tableContent);
32466 mapTimeObject.setIndex(index);
32467 mapTimeObjects.push(mapTimeObject);
32468 } catch(e) {
32469 continue;
32470 }
32471 }
32472
32473 if (GeoTemConfig.loadColorFromDataset)
32474 GeoTemConfig.loadDataObjectColoring(mapTimeObjects);
32475
32476 return mapTimeObjects;
32477 }
32478 /**
32479 * converts a KML dom into an array of data objects
32480 * @param {XML dom} kml the XML dom for the KML file
32481 * @return an array of data objects
32482 */
32483 GeoTemConfig.loadKml = function(kml) {
32484 var mapObjects = [];
32485 var elements = kml.getElementsByTagName("Placemark");
32486 if (elements.length == 0) {
32487 return [];
32488 }
32489 var index = 0;
32490 var descriptionTableHeaders = [];
32491 var xmlSerializer = new XMLSerializer();
32492
32493 for (var i = 0; i < elements.length; i++) {
32494 var placemark = elements[i];
32495 var name, description, place, granularity, lon, lat, tableContent = [], time = [], location = [];
32496 var weight = 1;
32497 var timeData = false, mapData = false;
32498
32499 try {
32500 description = placemark.getElementsByTagName("description")[0].childNodes[0].nodeValue;
32501
32502 //cleanWhitespace removes non-sense text-nodes (space, tab)
32503 //and is an addition to jquery defined above
32504 try {
32505 var descriptionDocument = $($.parseXML(description)).cleanWhitespace();
32506
32507 //check whether the description element contains a table
32508 //if yes, this data will be loaded as separate columns
32509 $(descriptionDocument).find("table").each(function(){
32510 $(this).find("tr").each(
32511 function() {
32512 var isHeader = true;
32513 var lastHeader = "";
32514
32515 $(this).find("td").each(
32516 function() {
32517 if (isHeader) {
32518 lastHeader = $.trim($(this).text());
32519 isHeader = false;
32520 } else {
32521 var value = "";
32522
32523 //if this td contains HTML, serialize all
32524 //it's children (the "content"!)
32525 $(this).children().each(
32526 function() {
32527 value += xmlSerializer.serializeToString(this);
32528 }
32529 );
32530
32531 //no HTML content (or no content at all)
32532 if (value.length == 0)
32533 value = $(this).text();
32534 if (typeof value === "undefined")
32535 value = "";
32536
32537 if ($.inArray(lastHeader, descriptionTableHeaders) === -1)
32538 descriptionTableHeaders.push(lastHeader);
32539
32540 if (tableContent[lastHeader] != null)
32541 //append if a field occures more than once
32542 tableContent[lastHeader] += "\n" + value;
32543 else
32544 tableContent[lastHeader] = value;
32545
32546 isHeader = true;
32547 }
32548 }
32549 );
32550 }
32551 );
32552 });
32553 } catch(e) {
32554 //couldn't be parsed, so it contains no html table
32555 //or is not in valid XHTML syntax
32556 }
32557
32558 //check whether the description element contains content in the form of equations
32559 //e.g. someDescriptor = someValue, where these eqations are separated by <br/>
32560 //if yes, this data will be loaded as separate columns
32561 var descriptionRows = description.replace(/<\s*br\s*[\/]*\s*>/g,"<br/>");
32562 $(descriptionRows.split("<br/>")).each(function(){
32563 var row = this;
32564
32565 if (typeof row === "undefined")
32566 return;
32567
32568 var headerAndValue = row.split("=");
32569 if (headerAndValue.length != 2)
32570 return;
32571
32572 var header = $.trim(headerAndValue[0]);
32573 var value = $.trim(headerAndValue[1]);
32574
32575 if ($.inArray(header, descriptionTableHeaders) === -1)
32576 descriptionTableHeaders.push(header);
32577
32578 if (tableContent[header] != null)
32579 //append if a field occures more than once
32580 tableContent[header] += "\n" + value;
32581 else
32582 tableContent[header] = value;
32583 });
32584
32585 tableContent["description"] = description;
32586 } catch(e) {
32587 description = "";
32588 }
32589
32590 try {
32591 name = placemark.getElementsByTagName("name")[0].childNodes[0].nodeValue;
32592 tableContent["name"] = name;
32593 } catch(e) {
32594 if (typeof tableContent["name"] !== "undefined")
32595 name = tableContent["name"];
32596 else
32597 name = "";
32598 }
32599
32600 try {
32601 place = placemark.getElementsByTagName("address")[0].childNodes[0].nodeValue;
32602 tableContent["place"] = place;
32603 } catch(e) {
32604 if (typeof tableContent["place"] !== "undefined")
32605 place = tableContent["place"];
32606 else
32607 place = "";
32608 }
32609
32610 try {
32611 var coordinates = placemark.getElementsByTagName("Point")[0].getElementsByTagName("coordinates")[0].childNodes[0].nodeValue;
32612 var lonlat = coordinates.split(",");
32613 lon = lonlat[0];
32614 lat = lonlat[1];
32615 if (lon == "" || lat == "" || isNaN(lon) || isNaN(lat)) {
32616 throw "e";
32617 }
32618 location.push({
32619 longitude : lon,
32620 latitude : lat,
32621 place : place
32622 });
32623 } catch(e) {
32624 if (!GeoTemConfig.incompleteData) {
32625 continue;
32626 }
32627 }
32628
32629 try {
32630 var tuple = GeoTemConfig.getTimeData(placemark.getElementsByTagName("TimeStamp")[0].getElementsByTagName("when")[0].childNodes[0].nodeValue);
32631 if (tuple != null) {
32632 time.push(tuple);
32633 timeData = true;
32634 } else if (!GeoTemConfig.incompleteData) {
32635 continue;
32636 }
32637 } catch(e) {
32638 try {
32639 if ( (typeof tableContent["TimeSpan:begin"] === "undefined") &&
32640 (typeof tableContent["TimeSpan:end"] === "undefined") ){
32641 var timeStart = $(placemark).find("TimeSpan begin").text();
32642 var timeEnd = $(placemark).find("TimeSpan end").text();
32643
32644 if ( (timeStart != "") && (timeStart != "") ){
32645 tableContent["TimeSpan:begin"] = timeStart;
32646 tableContent["TimeSpan:end"] = timeEnd;
32647
32648 timeData = true;
32649 }
32650 }
32651 } catch(e) {
32652 if (!GeoTemConfig.incompleteData) {
32653 continue;
32654 }
32655 }
32656 }
32657 var object = new DataObject(name, description, location, time, 1, tableContent);
32658 object.setIndex(index);
32659 index++;
32660 mapObjects.push(object);
32661 }
32662
32663 //make sure that all "description table" columns exists in all rows
32664 if (descriptionTableHeaders.length > 0){
32665 $(mapObjects).each(function(){
32666 var object = this;
32667 $(descriptionTableHeaders).each(function(){
32668 if (typeof object.tableContent[this] === "undefined")
32669 object.tableContent[this] = "";
32670 });
32671 });
32672 }
32673
32674 if (GeoTemConfig.loadColorFromDataset)
32675 GeoTemConfig.loadDataObjectColoring(mapObjects);
32676
32677 return mapObjects;
32678 };
32679
32680 GeoTemConfig.createKMLfromDataset = function(index){
32681 var kmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document>";
32682
32683 //credits: Anatoly Mironov, http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript
32684 function pad(number) {
32685 var r = String(number);
32686 if ( r.length === 1 ) {
32687 r = '0' + r;
32688 }
32689 return r;
32690 }
32691
32692 var dateToISOString = function(date, granularity) {
32693 var ISOString = date.getFullYear();
32694
32695 if (granularity <= SimileAjax.DateTime.MONTH)
32696 ISOString += '-' + pad( date.getMonth() + 1 );
32697 if (granularity <= SimileAjax.DateTime.DAY)
32698 ISOString += '-' + pad( date.getDate() );
32699 if (granularity <= SimileAjax.DateTime.HOUR){
32700 ISOString += 'T' + pad( date.getHours() );
32701 if (granularity <= SimileAjax.DateTime.MINUTE)
32702 ISOString += ':' + pad( date.getMinutes() );
32703 if (granularity <= SimileAjax.DateTime.SECOND)
32704 ISOString += ':' + pad( date.getSeconds() );
32705 if (granularity <= SimileAjax.DateTime.MILLISECOND)
32706 ISOString += '.' + String( (date.getMilliseconds()/1000).toFixed(3) ).slice( 2, 5 );
32707 ISOString += 'Z';
32708 }
32709
32710 return ISOString;
32711 };
32712
32713 $(GeoTemConfig.datasets[index].objects).each(function(){
32714 var name = this.name;
32715 var description = this.description;
32716 //TODO: allow multiple time/date
32717 var place = this.getPlace(0,0);
32718 var lat = this.getLatitude(0);
32719 var lon = this.getLongitude(0);
32720
32721 var kmlEntry = "<Placemark>";
32722
32723 kmlEntry += "<name><![CDATA[" + name + "]]></name>";
32724 kmlEntry += "<address><![CDATA[" + place + "]]></address>";
32725 kmlEntry += "<description><![CDATA[" + description + "]]></description>";
32726 kmlEntry += "<Point><coordinates>" + lon + "," + lat + "</coordinates></Point>";
32727
32728 if (this.isTemporal){
32729 kmlEntry += "<TimeStamp><when>" + dateToISOString(this.getDate(0), this.getTimeGranularity(0)) + "</when></TimeStamp>";
32730 } else if (this.isFuzzyTemporal){
32731 kmlEntry += "<TimeSpan>"+
32732 "<begin>" + dateToISOString(this.TimeSpanBegin.utc().toDate(), this.TimeSpanBeginGranularity) + "</begin>" +
32733 "<end>" + dateToISOString(this.TimeSpanEnd.utc().toDate(), this.TimeSpanEndGranularity) + "</end>" +
32734 "</TimeSpan>";
32735 }
32736
32737 kmlEntry += "</Placemark>";
32738
32739 kmlContent += kmlEntry;
32740 });
32741
32742 kmlContent += "</Document></kml>";
32743
32744 return(kmlContent);
32745 };
32746
32747 GeoTemConfig.createCSVfromDataset = function(index){
32748 var csvContent = "";
32749 var header = ["name", "description", "weight"];
32750 var tableContent = [];
32751
32752 var firstDataObject = GeoTemConfig.datasets[index].objects[0];
32753
32754 for(var key in firstDataObject.tableContent){
32755 var found = false;
32756 $(header).each(function(index,val){
32757 if (val === key){
32758 found = true;
32759 return false;
32760 }
32761 });
32762 if (found === true)
32763 continue;
32764 else
32765 tableContent.push(key);
32766 }
32767
32768 var isFirst = true;
32769 $(header).each(function(key,val){
32770 if (isFirst){
32771 isFirst = false;
32772 } else {
32773 csvContent += ",";
32774 }
32775
32776 //Rename according to CSV import definition
32777 if (val === "name")
32778 val = "Name";
32779 else if (val === "description")
32780 val = "Description";
32781 csvContent += "\""+val+"\"";
32782 });
32783 $(tableContent).each(function(key,val){
32784 if (isFirst){
32785 isFirst = false;
32786 } else {
32787 csvContent += ",";
32788 }
32789 csvContent += "\""+val+"\"";
32790 });
32791 //Names according to CSV import definition
32792 csvContent += ",\"Address\",\"Latitude\",\"Longitude\",\"TimeStamp\"";
32793 csvContent += "\n";
32794
32795 var isFirstRow = true;
32796 $(GeoTemConfig.datasets[index].objects).each(function(){
32797 var elem = this;
32798
32799 if (isFirstRow){
32800 isFirstRow = false;
32801 } else {
32802 csvContent += "\n";
32803 }
32804
32805 var isFirst = true;
32806 $(header).each(function(key,val){
32807 if (isFirst){
32808 isFirst = false;
32809 } else {
32810 csvContent += ",";
32811 }
32812 csvContent += "\""+elem[val]+"\"";
32813 });
32814 $(tableContent).each(function(key,val){
32815 if (isFirst){
32816 isFirst = false;
32817 } else {
32818 csvContent += ",";
32819 }
32820 csvContent += "\""+elem.tableContent[val]+"\"";
32821 });
32822
32823 csvContent += ",";
32824 csvContent += "\"";
32825 if (elem.isGeospatial){
32826 csvContent += elem.locations[0].place;
32827 }
32828 csvContent += "\"";
32829
32830 csvContent += ",";
32831 csvContent += "\"";
32832 if ( (elem.isGeospatial) && (typeof elem.getLatitude(0) !== "undefined") ){
32833 csvContent += elem.getLatitude(0);
32834 }
32835 csvContent += "\"";
32836
32837 csvContent += ",";
32838 csvContent += "\"";
32839 if ( (elem.isGeospatial) && (typeof elem.getLongitude(0) !== "undefined") ){
32840 csvContent += elem.getLongitude(0);
32841 }
32842 csvContent += "\"";
32843
32844 csvContent += ",";
32845 csvContent += "\"";
32846 if ( (elem.isTemporal) && (typeof elem.getDate(0) !== "undefined") ){
32847 //TODO: not supported in IE8 switch to moment.js
32848 csvContent += elem.getDate(0).toISOString();
32849 }
32850 csvContent += "\"";
32851 });
32852
32853 return(csvContent);
32854 };
32855 /**
32856 * iterates over Datasets/DataObjects and loads color values
32857 * from the "color0" and "color1" elements, which contains RGB
32858 * values in hex (CSS style #RRGGBB)
32859 * @param {dataObjects} array of DataObjects
32860 */
32861 GeoTemConfig.loadDataObjectColoring = function(dataObjects) {
32862 $(dataObjects).each(function(){
32863 var r0,g0,b0,r1,g1,b1;
32864 if ( (typeof this.tableContent !== "undefined") &&
32865 (typeof this.tableContent["color0"] !== "undefined") ){
32866 var color = this.tableContent["color0"];
32867 if ( (color.indexOf("#") == 0) && (color.length == 7) ){
32868 r0 = parseInt("0x"+color.substr(1,2));
32869 g0 = parseInt("0x"+color.substr(3,2));
32870 b0 = parseInt("0x"+color.substr(5,2));
32871 }
32872 }
32873 if ( (typeof this.tableContent !== "undefined") &&
32874 (typeof this.tableContent["color1"] !== "undefined") ){
32875 var color = this.tableContent["color1"];
32876 if ( (color.indexOf("#") == 0) && (color.length == 7) ){
32877 r1 = parseInt("0x"+color.substr(1,2));
32878 g1 = parseInt("0x"+color.substr(3,2));
32879 b1 = parseInt("0x"+color.substr(5,2));
32880 }
32881 }
32882
32883 if ( (typeof r0 !== "undefined") && (typeof g0 !== "undefined") && (typeof b0 !== "undefined") &&
32884 (typeof r1 !== "undefined") && (typeof g1 !== "undefined") && (typeof b1 !== "undefined") ){
32885 this.setColor(r0,g0,b0,r1,g1,b1);
32886 delete this.tableContent["color0"];
32887 delete this.tableContent["color1"];
32888 } else {
32889 if ((GeoTemConfig.debug)&&(typeof console !== undefined))
32890 console.error("Object '" + this.name + "' has invalid color information");
32891 }
32892 });
32893 };
32894
32895 /**
32896 * renames (or copies, see below) a column of each DataObject in a Dataset
32897 * @param {Dataset} dataset the dataset where the rename should take place
32898 * @param {String} oldColumn name of column that will be renamed
32899 * @param {String} newColumn new name of column
32900 * @param {Boolean} keepOld keep old column (copy mode)
32901 * @return an array of data objects
32902 */
32903 GeoTemConfig.renameColumns = function(dataset, renames){
32904 if (renames.length===0){
32905 return;
32906 }
32907 for (var renCnt = 0; renCnt < renames.length; renCnt++){
32908 var oldColumn = renames[renCnt].oldColumn;
32909 var newColumn = renames[renCnt].newColumn;
32910
32911 var keepOld = renames[renCnt].keepOld;
32912 if (typeof keepOld === "undefined"){
32913 keepOld = true;
32914 }
32915 var oldColumObject = {};
32916 if (oldColumn.indexOf("[") != -1){
32917 oldColumObject.columnName = oldColumn.split("[")[0];
32918 var IndexAndAttribute = oldColumn.split("[")[1];
32919 if (IndexAndAttribute.indexOf("]") != -1){
32920 oldColumObject.type = 2;
32921 oldColumObject.arrayIndex = IndexAndAttribute.split("]")[0];
32922 var attribute = IndexAndAttribute.split("]")[1];
32923 if (attribute.length > 0){
32924 oldColumObject.type = 3;
32925 oldColumObject.attribute = attribute.split(".")[1];
32926 }
32927 }
32928 } else {
32929 oldColumObject.type = 1;
32930 oldColumObject.name = oldColumn;
32931 }
32932
32933 var newColumObject = {};
32934 if (newColumn.indexOf("[") != -1){
32935 newColumObject.name = newColumn.split("[")[0];
32936 var IndexAndAttribute = newColumn.split("[")[1];
32937 if (IndexAndAttribute.indexOf("]") != -1){
32938 newColumObject.type = 2;
32939 newColumObject.arrayIndex = IndexAndAttribute.split("]")[0];
32940 var attribute = IndexAndAttribute.split("]")[1];
32941 if (attribute.length > 0){
32942 newColumObject.type = 3;
32943 newColumObject.attribute = attribute.split(".")[1];
32944 }
32945 }
32946 } else {
32947 newColumObject.type = 1;
32948 newColumObject.name = newColumn;
32949 }
32950
32951 for (var i = 0; i < dataset.objects.length; i++){
32952 var dataObject = dataset.objects[i];
32953
32954 //get value from old column name
32955 var value;
32956 if (oldColumObject.type == 1){
32957 value = dataObject[oldColumObject.name];
32958 if (typeof value === "undefined"){
32959 value = dataObject.tableContent[oldColumObject.name];
32960 }
32961 if (!keepOld){
32962 delete dataObject.tableContent[oldColumObject.name];
32963 delete dataObject[oldColumObject.name];
32964 }
32965 } else if (oldColumObject.type == 2){
32966 value = dataObject[oldColumObject.name][oldColumObject.arrayIndex];
32967 if (!keepOld){
32968 delete dataObject[oldColumObject.name][oldColumObject.arrayIndex];
32969 }
32970 } else if (oldColumObject.type == 3){
32971 value = dataObject[oldColumObject.name][oldColumObject.arrayIndex][oldColumObject.attribute];
32972 if (!keepOld){
32973 delete dataObject[oldColumObject.name][oldColumObject.arrayIndex][oldColumObject.attribute];
32974 }
32975 }
32976
32977 //create new column
32978 if (newColumObject.type == 1){
32979 dataObject[newColumObject.name] = value;
32980 dataObject.tableContent[newColumObject.name] = value;
32981 } else if (newColumObject.type == 2){
32982 if (typeof dataObject[newColumObject.name] == "undefined"){
32983 dataObject[newColumObject.name] = [];
32984 }
32985 dataObject[newColumObject.name][newColumObject.arrayIndex] = value;
32986 } else if (newColumObject.type == 3){
32987 if (typeof dataObject[newColumObject.name] == "undefined"){
32988 dataObject[newColumObject.name] = [];
32989 }
32990 if (typeof dataObject[newColumObject.name][newColumObject.arrayIndex] == "undefined"){
32991 dataObject[newColumObject.name][newColumObject.arrayIndex] = {};
32992 }
32993 dataObject[newColumObject.name][newColumObject.arrayIndex][newColumObject.attribute] = value;
32994 }
32995 }
32996 }
32997
32998 //actually create new dataObjects
32999 for (var i = 0; i < dataset.objects.length; i++){
33000 var dataObject = dataset.objects[i];
33001 //save index
33002 var index = dataObject.index;
33003
33004 dataset.objects[i] = new DataObject(dataObject.name, dataObject.description, dataObject.locations,
33005 dataObject.dates, dataObject.weight, dataObject.tableContent, dataObject.projection);
33006 //set index
33007 dataset.objects[i].setIndex(index);
33008 }
33009 };
33010 /*
33011 * MapControl.js
33012 *
33013 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
33014 *
33015 * This library is free software; you can redistribute it and/or
33016 * modify it under the terms of the GNU Lesser General Public
33017 * License as published by the Free Software Foundation; either
33018 * version 3 of the License, or (at your option) any later version.
33019 *
33020 * This library is distributed in the hope that it will be useful,
33021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33023 * Lesser General Public License for more details.
33024 *
33025 * You should have received a copy of the GNU Lesser General Public
33026 * License along with this library; if not, write to the Free Software
33027 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33028 * MA 02110-1301 USA
33029 */
33030
33031 /**
33032 * @class MapControl
33033 * Generic map control interface
33034 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
33035 * @release 1.0
33036 * @release date: 2012-07-27
33037 * @version date: 2012-07-27
33038 */
33039 function MapControl(map, button, label, onActivate, onDeactivate) {
33040
33041 var control = this;
33042 this.button = button;
33043 this.enabled = true;
33044 this.activated = false;
33045 this.label = label;
33046
33047 if (this.button != null) {
33048 $(this.button).addClass(label + 'Deactivated');
33049 $(this.button).attr("title", GeoTemConfig.getString(GeoTemConfig.language, label));
33050 //vhz
33051 $(this.button).click(function() {
33052 control.checkStatus();
33053 });
33054 }
33055
33056 this.checkStatus = function() {
33057 if (control.enabled) {
33058 if ( typeof map.activeControl != 'undefined') {
33059 if (control.activated) {
33060 control.deactivate();
33061 } else {
33062 map.activeControl.deactivate();
33063 control.activate();
33064 }
33065 } else {
33066 control.activate();
33067 }
33068 }
33069 };
33070
33071 this.setButtonClass = function(removeClass, addClass) {
33072 if (this.button != null) {
33073 $(this.button).removeClass(label + removeClass);
33074 $(this.button).addClass(label + addClass);
33075 $(this.button).attr("title", GeoTemConfig.getString(GeoTemConfig.language, label));
33076 }
33077 };
33078
33079 this.disable = function() {
33080 this.enabled = false;
33081 this.setButtonClass('Deactivated', 'Disabled');
33082 };
33083
33084 this.enable = function() {
33085 this.enabled = true;
33086 this.setButtonClass('Disabled', 'Deactivated');
33087 };
33088
33089 this.activate = function() {
33090 onActivate();
33091 this.activated = true;
33092 this.setButtonClass('Deactivated', 'Activated');
33093 map.activeControl = this;
33094 };
33095
33096 this.deactivate = function() {
33097 onDeactivate();
33098 this.activated = false;
33099 this.setButtonClass('Activated', 'Deactivated');
33100 map.activeControl = undefined;
33101 };
33102
33103 };
33104 /*
33105 * CircleObject.js
33106 *
33107 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
33108 *
33109 * This library is free software; you can redistribute it and/or
33110 * modify it under the terms of the GNU Lesser General Public
33111 * License as published by the Free Software Foundation; either
33112 * version 3 of the License, or (at your option) any later version.
33113 *
33114 * This library is distributed in the hope that it will be useful,
33115 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33116 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33117 * Lesser General Public License for more details.
33118 *
33119 * You should have received a copy of the GNU Lesser General Public
33120 * License along with this library; if not, write to the Free Software
33121 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33122 * MA 02110-1301 USA
33123 */
33124
33125 /**
33126 * @class CircleObject
33127 * circle object aggregate for the map
33128 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
33129 * @release 1.0
33130 * @release date: 2012-07-27
33131 * @version date: 2012-07-27
33132 *
33133 * @param {float} x the x (longitude) value for the circle
33134 * @param {float} y the y (latitude) value for the circle
33135 * @param {DataObject[]} elements array of data objects belonging to the circle
33136 * @param {float} radius the resulting radius (in pixel) for the circle
33137 * @param {int} search dataset index
33138 * @param {int} weight summed weight of all elements
33139 * @param {JSON} fatherBin bin of the circle object if its part of a circle pack
33140 */
33141 CircleObject = function(originX, originY, shiftX, shiftY, elements, radius, search, weight, fatherBin) {
33142
33143 this.originX = originX;
33144 this.originY = originY;
33145 this.shiftX = shiftX;
33146 this.shiftY = shiftY;
33147 this.elements = elements;
33148 this.radius = radius;
33149 this.search = search;
33150 this.weight = weight;
33151 this.overlay = 0;
33152 this.overlayElements = [];
33153 this.smoothness = 0;
33154 this.fatherBin = fatherBin;
33155
33156 this.feature
33157 this.olFeature
33158 this.percentage = 0;
33159 this.selected = false;
33160
33161 };
33162
33163 CircleObject.prototype = {
33164
33165 /**
33166 * sets the OpenLayers point feature for this point object
33167 * @param {OpenLayers.Feature} pointFeature the point feature for this object
33168 */
33169 setFeature : function(feature) {
33170 this.feature = feature;
33171 },
33172
33173 /**
33174 * sets the OpenLayers point feature for this point object to manage its selection status
33175 * @param {OpenLayers.Feature} olPointFeature the overlay point feature for this object
33176 */
33177 setOlFeature : function(olFeature) {
33178 this.olFeature = olFeature;
33179 },
33180
33181 reset : function() {
33182 this.overlay = 0;
33183 this.overlayElements = [];
33184 this.smoothness = 0;
33185 },
33186
33187 setSelection : function(s) {
33188 this.selected = s;
33189 },
33190
33191 toggleSelection : function() {
33192 this.selected = !this.selected;
33193 }
33194 };
33195 /*
33196 * FilterBar.js
33197 *
33198 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
33199 *
33200 * This library is free software; you can redistribute it and/or
33201 * modify it under the terms of the GNU Lesser General Public
33202 * License as published by the Free Software Foundation; either
33203 * version 3 of the License, or (at your option) any later version.
33204 *
33205 * This library is distributed in the hope that it will be useful,
33206 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33207 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33208 * Lesser General Public License for more details.
33209 *
33210 * You should have received a copy of the GNU Lesser General Public
33211 * License along with this library; if not, write to the Free Software
33212 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33213 * MA 02110-1301 USA
33214 */
33215
33216 /**
33217 * @class FilterBar
33218 * Implementation for FilterBar Object
33219 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
33220 * @release 1.0
33221 * @release date: 2012-07-27
33222 * @version date: 2012-07-27
33223 *
33224 * @param {Object} parent parent to call filter functions
33225 * @param {HTML object} parentDiv div to append filter buttons
33226 */
33227 FilterBarFactory = {
33228 filterBarArray :[],
33229 push : function(newFilterBar){
33230 FilterBarFactory.filterBarArray.push(newFilterBar);
33231 },
33232 resetAll : function(show) {
33233 $(FilterBarFactory.filterBarArray).each(function(){
33234 if (show) {
33235 this.filter.setAttribute('class', 'smallButton filter');
33236 this.filterInverse.setAttribute('class', 'smallButton filterInverse');
33237 this.cancelSelection.setAttribute('class', 'smallButton filterCancel');
33238 } else {
33239 this.filter.setAttribute('class', 'smallButton filterDisabled');
33240 this.filterInverse.setAttribute('class', 'smallButton filterInverseDisabled');
33241 this.cancelSelection.setAttribute('class', 'smallButton filterCancelDisabled');
33242 }
33243 });
33244 }
33245 };
33246
33247 function FilterBar(parent, parentDiv) {
33248 FilterBarFactory.push(this);
33249
33250 var bar = this;
33251
33252 this.filter = document.createElement('div');
33253 this.filter.setAttribute('class', 'smallButton filterDisabled');
33254 this.filter.onclick = function() {
33255 parent.filtering();
33256 };
33257
33258 this.filterInverse = document.createElement('div');
33259 this.filterInverse.setAttribute('class', 'smallButton filterInverseDisabled');
33260 this.filterInverse.onclick = function() {
33261 parent.inverseFiltering();
33262 };
33263 if (!GeoTemConfig.inverseFilter) {
33264 this.filterInverse.style.display = 'none';
33265 }
33266
33267 this.cancelSelection = document.createElement('div');
33268 this.cancelSelection.setAttribute('class', 'smallButton filterCancelDisabled');
33269 this.cancelSelection.onclick = function() {
33270 parent.deselection();
33271 };
33272
33273 this.appendTo = function(parentDiv) {
33274 parentDiv.appendChild(this.filter);
33275 parentDiv.appendChild(this.filterInverse);
33276 parentDiv.appendChild(this.cancelSelection);
33277 }
33278 if ( typeof parentDiv != 'undefined') {
33279 this.appendTo(parentDiv);
33280 }
33281
33282 this.reset = function(show) {
33283 FilterBarFactory.resetAll(show);
33284 };
33285
33286 };
33287 /*
33288 * Selection.js
33289 *
33290 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
33291 *
33292 * This library is free software; you can redistribute it and/or
33293 * modify it under the terms of the GNU Lesser General Public
33294 * License as published by the Free Software Foundation; either
33295 * version 3 of the License, or (at your option) any later version.
33296 *
33297 * This library is distributed in the hope that it will be useful,
33298 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33299 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33300 * Lesser General Public License for more details.
33301 *
33302 * You should have received a copy of the GNU Lesser General Public
33303 * License along with this library; if not, write to the Free Software
33304 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33305 * MA 02110-1301 USA
33306 */
33307
33308 /**
33309 * @class Selection
33310 * Selection Class
33311 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
33312 * @release 1.0
33313 * @release date: 2012-07-27
33314 * @version date: 2012-07-27
33315 *
33316 * @param {Array} objects array of selected objects
33317 * @param {Object} widget which belongs to selection
33318 */
33319 function Selection(objects, widget) {
33320
33321 this.objects = objects;
33322 if ( typeof objects == 'undefined') {
33323 this.objects = [];
33324 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
33325 this.objects.push([]);
33326 }
33327 }
33328 this.widget = widget;
33329
33330 this.getObjects = function(widget) {
33331 if (!this.equal(widget)) {
33332 return this.objects;
33333 }
33334 this.objects = [];
33335 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
33336 this.objects.push([]);
33337 }
33338 return this.objects;
33339 };
33340
33341 this.equal = function(widget) {
33342 if (this.valid() && this.widget != widget) {
33343 return false;
33344 }
33345 return true;
33346 };
33347
33348 this.valid = function() {
33349 if ( typeof this.widget != 'undefined') {
33350 return true;
33351 }
33352 return false;
33353 };
33354
33355 this.loadAllObjects = function() {
33356 allObjects = [];
33357 $(GeoTemConfig.datasets).each(function(){
33358 var singleDatasetObjects = [];
33359 $(this.objects).each(function(){
33360 singleDatasetObjects.push(this);
33361 });
33362 allObjects.push(singleDatasetObjects);
33363 });
33364 this.objects = allObjects;
33365 };
33366 };
33367
33368 /*
33369 * PlacenameTags.js
33370 *
33371 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
33372 *
33373 * This library is free software; you can redistribute it and/or
33374 * modify it under the terms of the GNU Lesser General Public
33375 * License as published by the Free Software Foundation; either
33376 * version 3 of the License, or (at your option) any later version.
33377 *
33378 * This library is distributed in the hope that it will be useful,
33379 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33380 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33381 * Lesser General Public License for more details.
33382 *
33383 * You should have received a copy of the GNU Lesser General Public
33384 * License along with this library; if not, write to the Free Software
33385 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33386 * MA 02110-1301 USA
33387 */
33388
33389 /**
33390 * @class PlacenameTags
33391 * place labels computation for circles
33392 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
33393 * @release 1.0
33394 * @release date: 2012-07-27
33395 * @version date: 2012-07-27
33396 */
33397 function PlacenameTags(circle, map) {
33398
33399 this.circle = circle;
33400 this.map = map;
33401
33402 this.placeLabels
33403 this.selectedLabel
33404
33405 this.allLabel
33406 this.othersLabel
33407 this.unknownLabel
33408
33409 this.calculate = function() {
33410 this.calculateLabels();
33411 this.calculatePlacenameTags();
33412 }
33413
33414 this.calculateLabels = function() {
33415 var elements = this.circle.elements;
33416 var k = this.circle.search;
33417 var weight = 0;
33418 var labels = [];
33419
33420 var levelOfDetail = 0;
33421 if (this.map.options.placenameTagsStyle === 'zoom')
33422 levelOfDetail = this.map.getLevelOfDetail();
33423
33424 if (this.map.options.placenameTagsStyle === 'value'){
33425 //find max level that _all_ elements have a value for
33426 var maxLevel;
33427 for (var i = 0; i < elements.length; i++) {
33428 var level = elements[i].placeDetails[this.map.options.mapIndex].length-1;
33429
33430 if (typeof maxLevel === "undefined")
33431 maxLevel = level;
33432 if (maxLevel > level)
33433 maxLevel = level;
33434 //smallest level anyway, no need to look any further
33435 if (level == 0)
33436 break;
33437 }
33438 //search for highest level where the values differ
33439 for (levelOfDetail = 0; levelOfDetail < maxLevel; levelOfDetail++){
33440 var differenceFound = false;
33441 for (var i = 0; i < (elements.length-1); i++) {
33442 if ( elements[i].getPlace(this.map.options.mapIndex, levelOfDetail) !==
33443 elements[i+1].getPlace(this.map.options.mapIndex, levelOfDetail))
33444 differenceFound = true;
33445 }
33446 if (differenceFound === true)
33447 break;
33448 }
33449 }
33450
33451 for (var i = 0; i < elements.length; i++) {
33452 weight += elements[i].weight;
33453 var found = false;
33454 var label = elements[i].getPlace(this.map.options.mapIndex, levelOfDetail);
33455 if (label == "") {
33456 label = "unknown";
33457 }
33458 for (var j = 0; j < labels.length; j++) {
33459 if (labels[j].place == label) {
33460 labels[j].elements.push(elements[i]);
33461 labels[j].weight += elements[i].weight;
33462 found = true;
33463 break;
33464 }
33465 }
33466 if (!found) {
33467 labels.push({
33468 id : elements[i].name,
33469 place : label,
33470 elements : new Array(elements[i]),
33471 weight : elements[i].weight,
33472 index : k
33473 });
33474 }
33475 }
33476 var sortBySize = function(label1, label2) {
33477 if (label1.weight > label2.weight) {
33478 return -1;
33479 }
33480 return 1;
33481 }
33482 labels.sort(sortBySize);
33483 if (map.options.maxPlaceLabels) {
33484 var ml = map.options.maxPlaceLabels;
33485 if (ml == 1) {
33486 labels = [];
33487 labels.push({
33488 place : "all",
33489 elements : elements,
33490 weight : weight,
33491 index : k
33492 });
33493 }
33494 if (ml == 2) {
33495 ml++;
33496 }
33497 if (ml > 2 && labels.length + 1 > ml) {
33498 var c = [];
33499 var w = 0;
33500 for (var i = ml - 2; i < labels.length; i++) {
33501 c = c.concat(labels[i].elements);
33502 w += labels[i].weight;
33503 }
33504 labels = labels.slice(0, ml - 2);
33505 labels.push({
33506 place : "others",
33507 elements : c,
33508 weight : w,
33509 index : k
33510 });
33511 }
33512 }
33513 if (labels.length > 1) {
33514 labels.push({
33515 place : "all",
33516 elements : elements,
33517 weight : weight,
33518 index : k
33519 });
33520 }
33521 this.placeLabels = labels;
33522 };
33523
33524 this.calculatePlacenameTags = function() {
33525 var cloud = this;
33526 var c = GeoTemConfig.getColor(this.circle.search);
33527 if( map.options.useGraphics ){
33528 c = map.config.getGraphic(this.circle.search).color;
33529 }
33530 var color0 = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
33531 var color1 = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
33532 var allStyles = "", hoverStyle = "", highlightStyle = "", selectedStyle = "", unselectedStyle = "";
33533
33534 if (GeoTemConfig.ie) {
33535 highlightStyle += map.options.ieHighlightLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33536 hoverStyle += map.options.ieHoveredLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33537 selectedStyle += map.options.ieSelectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33538 unselectedStyle += map.options.ieUnselectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33539 } else {
33540 highlightStyle += map.options.highlightLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33541 hoverStyle += map.options.hoveredLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33542 selectedStyle += map.options.selectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33543 unselectedStyle += map.options.unselectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33544 }
33545
33546 var clickFunction = function(label) {
33547 label.div.onclick = function() {
33548 cloud.changeLabelSelection(label);
33549 }
33550 }
33551 var maxLabelSize = this.count
33552 for (var i = 0; i < this.placeLabels.length; i++) {
33553 var l = this.placeLabels[i];
33554 l.selected = false;
33555 var div = document.createElement("div");
33556 div.setAttribute('class', 'tagCloudItem');
33557 var fontSize = 1 + (l.weight - 1) / this.map.count * map.options.maxLabelIncrease;
33558 if (l.place == "all") {
33559 fontSize = 1;
33560 }
33561 div.style.fontSize = fontSize + "em";
33562 l.allStyle = allStyles + "font-size: " + fontSize + "em;";
33563 l.selectedStyle = selectedStyle;
33564 l.unselectedStyle = unselectedStyle;
33565 l.highlightStyle = highlightStyle;
33566 l.hoverStyle = hoverStyle;
33567 div.innerHTML = l.place + "<span style='font-size:" + (1 / fontSize) + "em'>&nbsp;(" + l.weight + ")</span>";
33568 l.div = div;
33569 clickFunction(l);
33570 }
33571 if (map.options.labelGrid) {
33572 this.showPlacelabels();
33573 } else {
33574 for (var i = 0; i < this.placeLabels.length; i++) {
33575 this.placeLabels[i].div.setAttribute('style', this.placeLabels[i].allStyle + "" + this.placeLabels[i].highlightStyle);
33576 }
33577 }
33578 };
33579
33580 this.selectLabel = function(label) {
33581 if ( typeof label == 'undefined') {
33582 label = this.placeLabels[this.placeLabels.length - 1];
33583 }
33584 if (this.map.popup) {
33585 this.map.popup.showLabelContent(label);
33586 }
33587 this.selectedLabel = label;
33588 this.selectedLabel.div.setAttribute('style', this.selectedLabel.allStyle + "" + this.selectedLabel.selectedStyle);
33589 this.map.mapLabelSelection(label);
33590 };
33591
33592 // changes selection between labels (click, hover)
33593 this.changeLabelSelection = function(label) {
33594 if (this.selectedLabel == label) {
33595 return;
33596 }
33597 if ( typeof this.selectedLabel != 'undefined') {
33598 this.selectedLabel.div.setAttribute('style', this.selectedLabel.allStyle + "" + this.selectedLabel.unselectedStyle);
33599 }
33600 this.selectLabel(label);
33601 };
33602
33603 this.showPlacelabels = function() {
33604 this.leftDiv = document.createElement("div");
33605 this.leftDiv.setAttribute('class', 'tagCloudDiv');
33606 this.map.gui.mapWindow.appendChild(this.leftDiv);
33607 this.rightDiv = document.createElement("div");
33608 this.rightDiv.setAttribute('class', 'tagCloudDiv');
33609 this.map.gui.mapWindow.appendChild(this.rightDiv);
33610 for (var i = 0; i < this.placeLabels.length; i++) {
33611 if (i % 2 == 0) {
33612 this.leftDiv.appendChild(this.placeLabels[i].div);
33613 } else {
33614 this.rightDiv.appendChild(this.placeLabels[i].div);
33615 }
33616 this.placeLabels[i].div.setAttribute('style', this.placeLabels[i].allStyle + "" + this.placeLabels[i].highlightStyle);
33617 }
33618 this.placeTagCloud();
33619 };
33620
33621 this.placeTagCloud = function() {
33622 var lonlat = new OpenLayers.LonLat(this.circle.feature.geometry.x, this.circle.feature.geometry.y);
33623 var pixel = map.openlayersMap.getPixelFromLonLat(lonlat);
33624 var radius = this.circle.feature.style.pointRadius;
33625 var lw = this.leftDiv.offsetWidth;
33626 var rw = this.rightDiv.offsetWidth;
33627 this.leftDiv.style.left = (pixel.x - radius - lw - 5) + "px";
33628 this.rightDiv.style.left = (pixel.x + radius + 5) + "px";
33629 var lh = this.leftDiv.offsetHeight;
33630 var rh = this.rightDiv.offsetHeight;
33631 var lt = pixel.y - lh / 2;
33632 var rt = pixel.y - rh / 2;
33633 this.leftDiv.style.top = lt + "px";
33634 this.rightDiv.style.top = rt + "px";
33635 };
33636
33637 this.remove = function() {
33638 $(this.leftDiv).remove();
33639 $(this.rightDiv).remove();
33640 };
33641
33642 };
33643
33644 function PackPlacenameTags(circle, map) {
33645
33646 this.circle = circle;
33647 this.map = map;
33648
33649 this.placeLabels
33650 this.selectedLabel
33651
33652 this.allLabel
33653 this.othersLabel
33654 this.unknownLabel
33655
33656 this.calculate = function() {
33657 this.calculateLabels();
33658 this.calculatePlacenameTags();
33659 }
33660
33661 this.getLabelList = function(circle) {
33662
33663 var elements = circle.elements;
33664 var k = circle.search;
33665 var weight = 0;
33666 var labels = [];
33667 var levelOfDetail = this.map.getLevelOfDetail();
33668 for (var i = 0; i < elements.length; i++) {
33669 weight += elements[i].weight;
33670 var found = false;
33671 var label = elements[i].getPlace(this.map.options.mapIndex, levelOfDetail);
33672 if (label == "") {
33673 label = "unknown";
33674 }
33675 for (var j = 0; j < labels.length; j++) {
33676 if (labels[j].place == label) {
33677 labels[j].elements.push(elements[i]);
33678 labels[j].weight += elements[i].weight;
33679 found = true;
33680 break;
33681 }
33682 }
33683 if (!found) {
33684 labels.push({
33685 id : elements[i].name,
33686 place : label,
33687 elements : new Array(elements[i]),
33688 weight : elements[i].weight,
33689 index : k
33690 });
33691 }
33692 }
33693 var sortBySize = function(label1, label2) {
33694 if (label1.weight > label2.weight) {
33695 return -1;
33696 }
33697 return 1;
33698 }
33699 labels.sort(sortBySize);
33700 var droppedLabels = [];
33701 if (map.options.maxPlaceLabels) {
33702 var ml = map.options.maxPlaceLabels;
33703 if (ml == 1) {
33704 labels = [];
33705 labels.push({
33706 place : "all",
33707 elements : elements,
33708 weight : weight,
33709 index : k
33710 });
33711 }
33712 if (ml == 2) {
33713 ml++;
33714 }
33715 if (ml > 2 && labels.length + 1 > ml) {
33716 var c = [];
33717 var w = 0;
33718 for (var i = ml - 2; i < labels.length; i++) {
33719 c = c.concat(labels[i].elements);
33720 w += labels[i].weight;
33721 droppedLabels.push(labels[i]);
33722 }
33723 labels = labels.slice(0, ml - 2);
33724 var ol = {
33725 place : "others",
33726 elements : c,
33727 weight : w,
33728 index : k
33729 };
33730 labels.push(ol);
33731 this.othersLabels.push(ol);
33732 }
33733 }
33734 if (labels.length > 1) {
33735 labels.push({
33736 place : "all",
33737 elements : elements,
33738 weight : weight,
33739 index : k
33740 });
33741 }
33742 this.placeLabels.push(labels);
33743 this.droppedLabels.push(droppedLabels);
33744 };
33745
33746 this.calculateLabels = function() {
33747 var circles = this.circle.circles;
33748 this.placeLabels = [];
33749 this.droppedLabels = [];
33750 this.othersLabels = [];
33751 for (var i = 0; i < circles.length; i++) {
33752 this.getLabelList(circles[i]);
33753 }
33754 };
33755
33756 this.calculatePlacenameTags = function() {
33757 var cloud = this;
33758
33759 var unselectedStyles = [];
33760 var selectedStyles = [];
33761 var hoverStyles = [];
33762
33763 for (var k = 0; k < this.placeLabels.length; k++) {
33764 var c = GeoTemConfig.getColor(this.circle.circles[k].search);
33765 if( map.options.useGraphics ){
33766 c = map.config.getGraphic(this.circle.circles[k].search).color;
33767 }
33768 var color0 = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
33769 var color1 = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
33770 var allStyles = "", hoverStyle = "", highlightStyle = "", selectedStyle = "", unselectedStyle = "";
33771
33772 if (GeoTemConfig.ie) {
33773 highlightStyle += map.options.ieHighlightLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33774 hoverStyle += map.options.ieHoveredLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33775 selectedStyle += map.options.ieSelectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33776 unselectedStyle += map.options.ieUnselectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33777 } else {
33778 highlightStyle += map.options.highlightLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33779 hoverStyle += map.options.hoveredLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33780 selectedStyle += map.options.selectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33781 unselectedStyle += map.options.unselectedLabel.replace(/COLOR1/g, color1).replace(/COLOR0/g, color0) + ";";
33782 }
33783
33784 allStyles += 'margin-right:5px;';
33785 allStyles += 'margin-left:5px;';
33786 unselectedStyles.push(unselectedStyle);
33787 selectedStyles.push(selectedStyle);
33788 hoverStyles.push(hoverStyle);
33789
33790 var clickFunction = function(label, id) {
33791 label.div.onmouseover = function() {
33792 if (!label.opposite) {
33793 var oppositeLabel, oppositeLabelDiv;
33794 label.div.setAttribute('style', allStyles + "" + selectedStyles[id]);
33795 var c = GeoTemConfig.getColor(id);
33796 if( map.options.useGraphics ){
33797 c = map.config.getGraphic(id).color;
33798 }
33799 var color0 = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
33800 if (id == 0) {
33801 for (var i = 0; i < cloud.droppedLabels[1].length; i++) {
33802 if (cloud.droppedLabels[1][i].place == label.place) {
33803 oppositeLabel = cloud.droppedLabels[1][i];
33804 cloud.rightDiv.appendChild(oppositeLabel.div);
33805 cloud.drawLine(cloud.ctxOl, label.div, oppositeLabel.div);
33806 var olDiv = cloud.othersLabels[1].div;
33807 olDiv.innerHTML = olDiv.innerHTML.replace(/\(\d*\)/g, '(' + (cloud.othersLabels[1].weight - oppositeLabel.weight) + ')');
33808 break;
33809 }
33810 }
33811 } else {
33812 for (var i = 0; i < cloud.droppedLabels[0].length; i++) {
33813 if (cloud.droppedLabels[0][i].place == label.place) {
33814 oppositeLabel = cloud.droppedLabels[0][i];
33815 cloud.leftDiv.appendChild(oppositeLabel.div);
33816 cloud.drawLine(cloud.ctxOl, oppositeLabel.div, label.div);
33817 var olDiv = cloud.othersLabels[0].div;
33818 olDiv.innerHTML = olDiv.innerHTML.replace(/\(\d*\)/g, '(' + (cloud.othersLabels[0].weight - oppositeLabel.weight) + ')');
33819 break;
33820 }
33821 }
33822 }
33823 if ( typeof oppositeLabel == 'undefined') {
33824 oppositeLabel = {
33825 div : cloud.naDiv
33826 };
33827 if (id == 0) {
33828 cloud.rightDiv.appendChild(cloud.naDiv);
33829 cloud.drawLine(cloud.ctxOl, label.div, cloud.naDiv);
33830 oppositeLabel.div.setAttribute('style', allStyles + "" + selectedStyles[1]);
33831 } else {
33832 cloud.leftDiv.appendChild(cloud.naDiv);
33833 cloud.drawLine(cloud.ctxOl, cloud.naDiv, label.div);
33834 oppositeLabel.div.setAttribute('style', allStyles + "" + selectedStyles[0]);
33835 }
33836 cloud.map.mapLabelHighlight(label);
33837 } else {
33838 cloud.map.mapLabelHighlight([label, oppositeLabel]);
33839 }
33840 label.div.onmouseout = function() {
33841 label.div.setAttribute('style', allStyles + "" + unselectedStyles[id]);
33842 var olDiv = cloud.othersLabels[0].div;
33843 olDiv.innerHTML = olDiv.innerHTML.replace(/\(\d*\)/g, '(' + cloud.othersLabels[0].weight + ')');
33844 var olDiv2 = cloud.othersLabels[1].div;
33845 olDiv2.innerHTML = olDiv2.innerHTML.replace(/\(\d*\)/g, '(' + cloud.othersLabels[1].weight + ')');
33846 $(oppositeLabel.div).remove();
33847 cloud.ctxOl.clearRect(0, 0, cloud.cvOl.width, cloud.cvOl.height);
33848 cloud.map.mapLabelHighlight();
33849 }
33850 }
33851 }
33852 }
33853 var maxLabelSize = this.count
33854 for (var i = 0; i < this.placeLabels[k].length; i++) {
33855 var l = this.placeLabels[k][i];
33856 l.selected = false;
33857 var div = document.createElement("div");
33858 div.setAttribute('class', 'tagCloudItem');
33859 var fontSize = 1 + (l.weight - 1) / this.map.count * map.options.maxLabelIncrease;
33860 if (l.place == "all") {
33861 fontSize = 1;
33862 }
33863 div.style.fontSize = fontSize + "em";
33864 l.allStyle = allStyles + "font-size: " + fontSize + "em;";
33865 l.selectedStyle = selectedStyle;
33866 l.unselectedStyle = unselectedStyle;
33867 l.hoverStyle = hoverStyle;
33868 div.innerHTML = l.place + "<span style='font-size:" + (1 / fontSize) + "em'>&nbsp;(" + l.weight + ")</span>";
33869 l.div = div;
33870 clickFunction(l, k);
33871 }
33872 for (var i = 0; i < this.droppedLabels[k].length; i++) {
33873 var l = this.droppedLabels[k][i];
33874 l.selected = false;
33875 var div = document.createElement("div");
33876 div.setAttribute('class', 'tagCloudItem');
33877 var fontSize = 1 + (l.weight - 1) / this.map.count * map.options.maxLabelIncrease;
33878 div.style.fontSize = fontSize + "em";
33879 l.allStyle = allStyles + "font-size: " + fontSize + "em;";
33880 l.selectedStyle = selectedStyle;
33881 l.unselectedStyle = unselectedStyle;
33882 l.hoverStyle = hoverStyle;
33883 div.innerHTML = l.place + "<span style='font-size:" + (1 / fontSize) + "em'>&nbsp;(" + l.weight + ")</span>";
33884 l.div = div;
33885 div.setAttribute('style', allStyles + "" + selectedStyle);
33886 }
33887 }
33888
33889 this.naDiv = document.createElement("div");
33890 this.naDiv.setAttribute('class', 'tagCloudItem');
33891 var fontSize = 1;
33892 div.style.fontSize = fontSize + "em";
33893 l.allStyle = allStyles + "font-size: " + fontSize + "em;";
33894 l.selectedStyle = selectedStyle;
33895 l.unselectedStyle = unselectedStyle;
33896 l.hoverStyle = hoverStyle;
33897 this.naDiv.innerHTML = "Not available";
33898 l.div = this.naDiv;
33899
33900 if (map.options.labelGrid) {
33901 this.showPlacelabels();
33902 }
33903 };
33904
33905 this.showPlacelabels = function() {
33906 this.leftDiv = document.createElement("div");
33907 this.leftDiv.setAttribute('class', 'tagCloudDiv');
33908 this.leftDiv.style.textAlign = 'right';
33909 this.map.gui.mapWindow.appendChild(this.leftDiv);
33910 this.centerDiv = document.createElement("div");
33911 this.centerDiv.setAttribute('class', 'tagCloudDiv');
33912 this.centerDiv.style.opacity = 0.7;
33913 this.map.gui.mapWindow.appendChild(this.centerDiv);
33914 this.centerDivOl = document.createElement("div");
33915 this.centerDivOl.setAttribute('class', 'tagCloudDiv');
33916 this.centerDivOl.style.opacity = 0.7;
33917 this.map.gui.mapWindow.appendChild(this.centerDivOl);
33918 this.rightDiv = document.createElement("div");
33919 this.rightDiv.setAttribute('class', 'tagCloudDiv');
33920 this.rightDiv.style.textAlign = 'left';
33921 this.map.gui.mapWindow.appendChild(this.rightDiv);
33922 for (var i = 0; i < this.placeLabels.length; i++) {
33923 for (var j = 0; j < this.placeLabels[i].length; j++) {
33924 if (i == 0) {
33925 this.leftDiv.appendChild(this.placeLabels[i][j].div);
33926 } else {
33927 this.rightDiv.appendChild(this.placeLabels[i][j].div);
33928 }
33929 this.placeLabels[i][j].div.setAttribute('style', this.placeLabels[i][j].allStyle + "" + this.placeLabels[i][j].unselectedStyle);
33930 }
33931 }
33932 this.placeTagCloud();
33933 this.setCanvas();
33934 };
33935
33936 this.placeTagCloud = function() {
33937 var lonlat = new OpenLayers.LonLat(this.circle.feature.geometry.x, this.circle.feature.geometry.y);
33938 var pixel = map.openlayersMap.getPixelFromLonLat(lonlat);
33939 var radius = this.circle.feature.style.pointRadius;
33940 var lw = this.leftDiv.offsetWidth;
33941 var rw = this.rightDiv.offsetWidth;
33942 this.leftDiv.style.left = (pixel.x - radius - lw - 5) + "px";
33943 this.rightDiv.style.left = (pixel.x + radius + 5) + "px";
33944 var lh = this.leftDiv.offsetHeight;
33945 var rh = this.rightDiv.offsetHeight;
33946 var lt = pixel.y - lh / 2;
33947 var rt = pixel.y - rh / 2;
33948 this.leftDiv.style.top = lt + "px";
33949 this.rightDiv.style.top = rt + "px";
33950 };
33951
33952 this.setCanvas = function() {
33953 var height = Math.max(this.leftDiv.offsetHeight, this.rightDiv.offsetHeight);
33954 var top = Math.min(this.leftDiv.offsetTop, this.rightDiv.offsetTop);
33955 var left = this.leftDiv.offsetLeft + this.leftDiv.offsetWidth;
33956 this.width = this.rightDiv.offsetLeft - left;
33957 this.centerDiv.style.left = left + "px";
33958 this.centerDiv.style.top = top + "px";
33959 this.centerDiv.style.height = height + "px";
33960 this.centerDiv.style.width = this.width + "px";
33961
33962 this.centerDivOl.style.left = left + "px";
33963 this.centerDivOl.style.top = top + "px";
33964 this.centerDivOl.style.height = height + "px";
33965 this.centerDivOl.style.width = this.width + "px";
33966
33967 var cv = document.createElement("canvas");
33968 this.centerDiv.appendChild(cv);
33969 if (!cv.getContext && G_vmlCanvasManager) {
33970 cv = G_vmlCanvasManager.initElement(cv);
33971 }
33972 cv.width = this.width;
33973 cv.height = height;
33974 ctx = cv.getContext('2d');
33975
33976 this.cvOl = document.createElement("canvas");
33977 this.centerDivOl.appendChild(this.cvOl);
33978 if (!this.cvOl.getContext && G_vmlCanvasManager) {
33979 this.cvOl = G_vmlCanvasManager.initElement(this.cvOl);
33980 }
33981 this.cvOl.width = this.width;
33982 this.cvOl.height = height + 50;
33983 this.ctxOl = this.cvOl.getContext('2d');
33984
33985 for (var i = 0; i < this.placeLabels[0].length; i++) {
33986 this.placeLabels[0][i].opposite = false;
33987 }
33988 for (var i = 0; i < this.placeLabels[1].length; i++) {
33989 this.placeLabels[1][i].opposite = false;
33990 }
33991 for (var i = 0; i < this.placeLabels[0].length; i++) {
33992 for (var j = 0; j < this.placeLabels[1].length; j++) {
33993 if (this.placeLabels[0][i].place == this.placeLabels[1][j].place) {
33994 this.drawLine(ctx, this.placeLabels[0][i].div, this.placeLabels[1][j].div);
33995 this.placeLabels[0][i].opposite = true;
33996 this.placeLabels[1][j].opposite = true;
33997 }
33998 }
33999 }
34000 }
34001
34002 this.drawLine = function(ctx, label1, label2) {
34003 var x1 = 5;
34004 var x2 = this.width - 5;
34005 var y1 = label1.offsetTop + label1.offsetHeight / 2;
34006 var y2 = label2.offsetTop + label2.offsetHeight / 2;
34007 if (this.leftDiv.offsetTop > this.rightDiv.offsetTop) {
34008 y1 += this.leftDiv.offsetTop - this.rightDiv.offsetTop;
34009 } else {
34010 y2 += this.rightDiv.offsetTop - this.leftDiv.offsetTop;
34011 }
34012 ctx.lineCap = 'round';
34013 ctx.lineWidth = 5;
34014 ctx.beginPath();
34015 ctx.moveTo(x1, y1);
34016 ctx.lineTo(x2, y2);
34017 ctx.strokeStyle = '#555';
34018 ctx.stroke();
34019 }
34020
34021 this.remove = function() {
34022 $(this.leftDiv).remove();
34023 $(this.rightDiv).remove();
34024 $(this.centerDiv).remove();
34025 $(this.centerDivOl).remove();
34026 };
34027
34028 };
34029 /*
34030 * MapConfig.js
34031 *
34032 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
34033 *
34034 * This library is free software; you can redistribute it and/or
34035 * modify it under the terms of the GNU Lesser General Public
34036 * License as published by the Free Software Foundation; either
34037 * version 3 of the License, or (at your option) any later version.
34038 *
34039 * This library is distributed in the hope that it will be useful,
34040 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34041 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34042 * Lesser General Public License for more details.
34043 *
34044 * You should have received a copy of the GNU Lesser General Public
34045 * License along with this library; if not, write to the Free Software
34046 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
34047 * MA 02110-1301 USA
34048 */
34049
34050 /**
34051 * @class MapConfig
34052 * Map Configuration File
34053 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
34054 * @release 1.0
34055 * @release date: 2012-07-27
34056 * @version date: 2012-07-27
34057 */
34058 function MapConfig(options) {
34059
34060 this.options = {
34061 mapWidth : false, // false or desired width css definition for the map
34062 mapHeight : '580px', // false or desired height css definition for the map
34063 mapTitle : 'GeoTemCo Map View', // title will be shown in map header
34064 mapIndex : 0, // index = position in location array; for multiple locations the 2nd map refers to index 1
34065 alternativeMap : [
34066 {
34067 name: 'Barrington Roman Empire',
34068 url: 'http://pelagios.dme.ait.ac.at/tilesets/imperium/${z}/${x}/${y}.png',
34069 type:'XYZ',
34070 attribution: "(c) Barrington Roman Empiry, <a href='http://pelagios.dme.ait.ac.at/maps/greco-roman/'>Pelagios</a>"
34071 },
34072 {
34073 name: 'Maps-for-Free Relief Map',
34074 url: 'http://maps-for-free.com/layer/relief/z${z}/row${y}/${z}_${x}-${y}.jpg',
34075 type:'XYZ',
34076 attribution: "(c) <a href='http://www.maps-for-free.com/html/about.html'>Maps for Free</a>"
34077 },
34078 {
34079 name: 'Contemporary Map (2010)',
34080 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34081 layer: 'historic:cntry2010',
34082 attribution: "(c) <a href='http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco_Geographical_information_maps/popups/references/administrative_units_statistical_units_1'>EuroStat</a>"
34083 },
34084 {
34085 name: 'Historical Map of 2006',
34086 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34087 layer: 'historic:cntry2006',
34088 attribution: "(c) <a href='http://epp.eurostat.ec.europa.eu/portal/page/portal/gisco_Geographical_information_maps/popups/references/administrative_units_statistical_units_1'>EuroStat</a>"
34089 },
34090 {
34091 name: 'Historical Map of 1994',
34092 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34093 layer: 'historic:cntry1994',
34094 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34095 },
34096 {
34097 name: 'Historical Map of 1945',
34098 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34099 layer: 'historic:cntry1945',
34100 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34101 },
34102 {
34103 name: 'Historical Map of 1938',
34104 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34105 layer: 'historic:cntry1938',
34106 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34107 },
34108 {
34109 name: 'Historical Map of 1920',
34110 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34111 layer: 'historic:cntry1920',
34112 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34113 },
34114 {
34115 name: 'Historical Map of 1914',
34116 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34117 layer: 'historic:cntry1914',
34118 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34119 },
34120 {
34121 name: 'Historical Map of 1880',
34122 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34123 layer: 'historic:cntry1880',
34124 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34125 },
34126 {
34127 name: 'Historical Map of 1815',
34128 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34129 layer: 'historic:cntry1815',
34130 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34131 },
34132 {
34133 name: 'Historical Map of 1783',
34134 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34135 layer: 'historic:cntry1783',
34136 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34137 },
34138 {
34139 name: 'Historical Map of 1715',
34140 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34141 layer: 'historic:cntry1715',
34142 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34143 },
34144 {
34145 name: 'Historical Map of 1650',
34146 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34147 layer: 'historic:cntry1650',
34148 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34149 },
34150 {
34151 name: 'Historical Map of 1530',
34152 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34153 layer: 'historic:cntry1530',
34154 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34155 },
34156 {
34157 name: 'Historical Map of 1492',
34158 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34159 layer: 'historic:cntry1492',
34160 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34161 },
34162 {
34163 name: 'Historical Map of 1279',
34164 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34165 layer: 'historic:cntry1279',
34166 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34167 },
34168 {
34169 name: 'Historical Map of 1000',
34170 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34171 layer: 'historic:cntry1000',
34172 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34173 },
34174 {
34175 name: 'Historical Map of 800',
34176 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34177 layer: 'historic:cntry800',
34178 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34179 },
34180 {
34181 name: 'Historical Map of 600',
34182 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34183 layer: 'historic:cntry600',
34184 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34185 },
34186 {
34187 name: 'Historical Map of 400',
34188 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34189 layer: 'historic:cntry400',
34190 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34191 },
34192 {
34193 name: 'Historical Map of 1 BC',
34194 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34195 layer: 'historic:cntry1bc',
34196 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34197 },
34198 {
34199 name: 'Historical Map of 200 BC',
34200 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34201 layer: 'historic:cntry200bc',
34202 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34203 },
34204 {
34205 name: 'Historical Map of 323 BC',
34206 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34207 layer: 'historic:cntry323bc',
34208 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34209 },
34210 {
34211 name: 'Historical Map of 500 BC',
34212 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34213 layer: 'historic:cntry500bc',
34214 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34215 },
34216 {
34217 name: 'Historical Map of 1000 BC',
34218 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34219 layer: 'historic:cntry1000bc',
34220 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34221 },
34222 {
34223 name: 'Historical Map of 2000 BC',
34224 url: 'http://geoserver.mpiwg-berlin.mpg.de/geoserver/mpiwg/wms',
34225 layer: 'historic:cntry2000bc',
34226 attribution: "(c) <a href='http://webcache.googleusercontent.com/search?q=cache:NbaEeiehhzQJ:library.thinkquest.org/C006628/citations.html&client=ubuntu&hl=de&gl=de&strip=1'> ThinkQuest Team C006628</a>"
34227 },
34228 ],
34229 legend : true, // if a legend at the bottom of the map should be shown or not
34230 mapMerge : false, // if the elements of distinct datasets should be merged into one set or not
34231 useGraphics : false, // if different graphics should represent different datasets or not
34232 graphics : [
34233 {
34234 shape: "circle",
34235 rotation: 0
34236 },
34237 {
34238 shape: "square",
34239 rotation: 0
34240 },
34241 {
34242 shape: "triangle",
34243 rotation: 0
34244 },
34245 {
34246 shape: "square",
34247 rotation: 45
34248 }
34249 ],
34250 googleMaps : false, // enable/disable Google maps (actually, no Google Maps API key is required)
34251 bingMaps : false, // enable/disable Bing maps (you need to set the Bing Maps API key below)
34252 bingApiKey : 'none', // bing maps api key, see informations at http://bingmapsportal.com/
34253 osmMaps : true, // enable/disable OSM maps
34254 osmMapsMapQuest : true, // enable/disable OSM maps with MapQuest tiles
34255 baseLayer : 'Open Street Map', // initial layer to show (e.g. 'Google Streets')
34256 resetMap : true, // show/hide map reset button
34257 countrySelect : true, // show/hide map country selection control button
34258 polygonSelect : true, // show/hide map polygon selection control button
34259 circleSelect : true, // show/hide map circle selection control button
34260 squareSelect : true, // show/hide map square selection control button
34261 multiSelection : true, // true, if multiple polygons or multiple circles should be selectable
34262 popups : true, // enabled popups will show popup windows for circles on the map
34263 olNavigation : false, // show/hide OpenLayers navigation panel
34264 olLayerSwitcher : false, // show/hide OpenLayers layer switcher
34265 olMapOverview : false, // show/hide OpenLayers map overview
34266 olKeyboardDefaults : true, // (de)activate Openlayers keyboard defaults
34267 olScaleLine : false, // (de)activate Openlayers keyboard defaults
34268 geoLocation : true, // show/hide GeoLocation feature
34269 boundaries : {
34270 minLon : -29,
34271 minLat : 35,
34272 maxLon : 44,
34273 maxLat : 67
34274 }, // initial map boundaries or 'false' for no boundaries
34275 mapBackground : '#bbd0ed',
34276 labelGrid : true, // show label grid on hover
34277 maxPlaceLabels : 6, // Integer value for fixed number of place labels: 0 --> unlimited, 1 --> 1 label (won't be shown in popup, 2 --> is not possible because of others & all labels --> 3 labels, [3,...,N] --> [3,...,N] place labels)
34278 selectDefault : true, // true, if strongest label should be selected as default
34279 maxLabelIncrease : 2, // maximum increase (in em) for the font size of a label
34280 labelHover : false, // true, to update on label hover
34281 ieHighlightLabel : "color: COLOR1; background-color: COLOR0; filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)';-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)';", // css code for a highlighted place label in IE
34282 highlightLabel : "color: COLOR0; text-shadow: 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em COLOR0;", // css code for a highlighted place label
34283 ieSelectedLabel : "color: COLOR1; font-weight: bold;", // css code for a selected place label in IE
34284 selectedLabel : "color: COLOR1; font-weight: bold;", // css code for a selected place label
34285 ieUnselectedLabel : "color: COLOR1; font-weight: normal;", // css code for an unselected place label in IE
34286 unselectedLabel : "color: COLOR1; font-weight: normal;", // css code for an unselected place label
34287 ieHoveredLabel : "color: COLOR1; font-weight: bold;", // css code for a hovered place label in IE
34288 hoveredLabel : "color: COLOR1; font-weight: bold;", // css code for a hovered place label
34289 circleGap : 0, // gap between the circles on the map (>=0)
34290 circleOverlap : {
34291 type: 'area', // 'area' or 'diameter' is possible
34292 overlap: 0 // the percentage of allowed overlap (0<=overlap<=1)
34293 }, // maximum allowed overlap in percent (if circleGap = 0, circleOverlap will be used)
34294 minimumRadius : 4, // minimum radius of a circle with mimimal weight (>0)
34295 circleOutline : 2, // false for no outline or a pixel value v with 0 < v
34296 circleOpacity : 'balloon', // 'balloon' for dynamic opacity of the circles or a value t with 0 <= t <= 1
34297 minTransparency : 0.55, // maximum transparency of a circle
34298 maxTransparency : 0.8, // minimum transparency of a circle
34299 binning : 'generic', // binning algorithm for the map, possible values are: 'generic', 'square', 'hexagonal', 'triangular' or false for 'no binning'
34300 noBinningRadii : 'dynamic', // for 'no binning': 'static' for only minimum radii, 'dynamic' for increasing radii for increasing weights
34301 circlePackings : true, // if circles of multiple result sets should be displayed in circle packs, if a binning is performed
34302 binCount : 10, // number of bins for x and y dimension for lowest zoom level
34303 showDescriptions : true, // true to show descriptions of data items (must be provided by kml/json), false if not
34304 mapSelection : true, // show/hide select map dropdown
34305 binningSelection : false, // show/hide binning algorithms dropdown
34306 mapSelectionTools : true, // show/hide map selector tools
34307 dataInformation : true, // show/hide data information
34308 overlayVisibility : false, // initial visibility of additional overlays
34309 //proxyHost : 'php/proxy.php?address=', //required for selectCountry feature, if the requested GeoServer and GeoTemCo are NOT on the same server
34310 placenameTagsStyle : 'value' // the style of the placenames "surrounding" a circle on hover. 'zoom' for tags based on zoom level (old behaviour), 'value' for new value-based
34311
34312 };
34313 if ( typeof options != 'undefined') {
34314 $.extend(this.options, options);
34315 }
34316
34317 //if the user can change shape/color graphics have to be used
34318 //but this will use circles as default shape
34319 if (GeoTemConfig.allowUserShapeAndColorChange){
34320 this.options.useGraphics = true;
34321 }
34322
34323 };
34324
34325 MapConfig.prototype.getGraphic = function(id){
34326 var dataset = GeoTemConfig.datasets[id];
34327
34328 var graphic;
34329 if (typeof dataset.graphic !== "undefined"){
34330 graphic = dataset.graphic;
34331 } else{
34332 graphic = this.options.graphics[id % this.options.graphics.length];
34333 }
34334
34335 var color;
34336 if (typeof dataset.color !== "undefined"){
34337 color = dataset.color;
34338 } else{
34339 color = GeoTemConfig.getColor(id);
34340 }
34341 return {
34342 shape: graphic.shape,
34343 rotation: graphic.rotation,
34344 color: color
34345 };
34346 };
34347 /*
34348 * MapGui.js
34349 *
34350 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
34351 *
34352 * This library is free software; you can redistribute it and/or
34353 * modify it under the terms of the GNU Lesser General Public
34354 * License as published by the Free Software Foundation; either
34355 * version 3 of the License, or (at your option) any later version.
34356 *
34357 * This library is distributed in the hope that it will be useful,
34358 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34359 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34360 * Lesser General Public License for more details.
34361 *
34362 * You should have received a copy of the GNU Lesser General Public
34363 * License along with this library; if not, write to the Free Software
34364 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
34365 * MA 02110-1301 USA
34366 */
34367
34368 /**
34369 * @class MapGui
34370 * Map GUI Implementation
34371 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
34372 * @release 1.0
34373 * @release date: 2012-07-27
34374 * @version date: 2012-07-27
34375 *
34376 * @param {MapWidget} parent map widget object
34377 * @param {HTML object} div parent div to append the map gui
34378 * @param {JSON} options map configuration
34379 */
34380 function MapGui(map, div, options, iid) {
34381
34382 this.map = map;
34383
34384 this.container = div;
34385 if (options.mapWidth) {
34386 this.container.style.width = options.mapWidth;
34387 }
34388 if (options.mapHeight) {
34389 this.container.style.height = options.mapHeight;
34390 }
34391 this.container.style.position = 'relative';
34392
34393 this.mapWindow = document.createElement("div");
34394 this.mapWindow.setAttribute('class', 'mapWindow');
34395 this.mapWindow.id = "mapWindow"+iid;
34396 this.mapWindow.style.background = options.mapBackground;
34397 this.container.appendChild(this.mapWindow);
34398
34399 this.mapContainer = document.createElement("div");
34400 this.mapContainer.setAttribute('class', 'mapContainer');
34401 this.mapContainer.id = "mapContainer"+iid;
34402 this.mapContainer.style.position = "absolute";
34403 this.mapContainer.style.zIndex = 0;
34404 this.mapWindow.appendChild(this.mapContainer);
34405
34406 var toolbarTable = document.createElement("table");
34407 toolbarTable.setAttribute('class', 'absoluteToolbar ddbToolbar');
34408 this.container.appendChild(toolbarTable);
34409 this.mapToolbar = toolbarTable;
34410
34411 var titles = document.createElement("tr");
34412 toolbarTable.appendChild(titles);
34413 var tools = document.createElement("tr");
34414 toolbarTable.appendChild(tools);
34415
34416 if (options.mapSelection) {
34417 this.mapTypeTitle = document.createElement("td");
34418 titles.appendChild(this.mapTypeTitle);
34419 this.mapTypeTitle.innerHTML = GeoTemConfig.getString('mapType');
34420 this.mapTypeSelector = document.createElement("td");
34421 tools.appendChild(this.mapTypeSelector);
34422 }
34423
34424 if (options.mapSelectionTools) {
34425 this.mapSelectorTitle = document.createElement("td");
34426 titles.appendChild(this.mapSelectorTitle);
34427 this.mapSelectorTitle.innerHTML = GeoTemConfig.getString('mapSelectorTools');
34428 var mapSelectorTools = document.createElement("td");
34429 var selectorTools = this.map.initSelectorTools();
34430 for (var i in selectorTools ) {
34431 mapSelectorTools.appendChild(selectorTools[i].button);
34432 }
34433 tools.appendChild(mapSelectorTools);
34434 }
34435
34436 if (options.binningSelection) {
34437 this.binningTitle = document.createElement("td");
34438 titles.appendChild(this.binningTitle);
34439 this.binningTitle.innerHTML = GeoTemConfig.getString('binningType');
34440 this.binningSelector = document.createElement("td");
34441 tools.appendChild(this.binningSelector);
34442 }
34443
34444 if (GeoTemConfig.allowFilter) {
34445 this.filterTitle = document.createElement("td");
34446 titles.appendChild(this.filterTitle);
34447 this.filterTitle.innerHTML = GeoTemConfig.getString('filter');
34448 this.filterOptions = document.createElement("td");
34449 tools.appendChild(this.filterOptions);
34450 }
34451
34452 if (options.dataInformation) {
34453 this.infoTitle = document.createElement("td");
34454 this.infoTitle.innerHTML = options.mapTitle;
34455 titles.appendChild(this.infoTitle);
34456 var mapSum = document.createElement("td");
34457 this.mapElements = document.createElement("div");
34458 this.mapElements.setAttribute('class', 'ddbElementsCount');
34459 mapSum.appendChild(this.mapElements);
34460 tools.appendChild(mapSum);
34461 }
34462
34463 this.lockTitle = document.createElement("td");
34464 titles.appendChild(this.lockTitle);
34465 this.lockIcon = document.createElement("td");
34466 var lockButton = document.createElement("div");
34467 $(lockButton).addClass('mapControl');
34468 var activateLock = function() {
34469 map.navigation.deactivate();
34470 }
34471 var deactivateLock = function() {
34472 map.navigation.activate();
34473 }
34474 var lockMapControl = new MapControl(this.map, lockButton, 'lock', activateLock, deactivateLock);
34475 tools.appendChild(lockMapControl.button);
34476
34477
34478 var gui = this;
34479 if (navigator.geolocation && options.geoLocation) {
34480 this.geoActive = false;
34481 this.geoLocation = document.createElement("div");
34482 this.geoLocation.setAttribute('class', 'geoLocationOff');
34483 this.geoLocation.title = GeoTemConfig.getString('activateGeoLocation');
34484 this.container.appendChild(this.geoLocation);
34485 this.geoLocation.style.left = "20px";
34486 this.geoLocation.onclick = function() {
34487 var changeStyle = function() {
34488 if (gui.geoActive) {
34489 gui.geoLocation.setAttribute('class', 'geoLocationOn');
34490 gui.geoLocation.title = GeoTemConfig.getString(GeoTemConfig.language, 'deactivateGeoLocation');
34491 } else {
34492 gui.geoLocation.setAttribute('class', 'geoLocationOff');
34493 gui.geoLocation.title = GeoTemConfig.getString(GeoTemConfig.language, 'activateGeoLocation');
34494 }
34495 }
34496 if (!gui.geoActive) {
34497 if ( typeof gui.longitude == 'undefined') {
34498 navigator.geolocation.getCurrentPosition(function(position) {
34499 gui.longitude = position.coords.longitude;
34500 gui.latitude = position.coords.latitude;
34501 gui.map.setMarker(gui.longitude, gui.latitude);
34502 gui.geoActive = true;
34503 changeStyle();
34504 }, function(msg) {
34505 console.log( typeof msg == 'string' ? msg : "error");
34506 });
34507 } else {
34508 gui.map.setMarker(gui.longitude, gui.latitude);
34509 gui.geoActive = true;
34510 changeStyle();
34511 }
34512 } else {
34513 gui.map.removeMarker();
34514 gui.geoActive = false;
34515 changeStyle();
34516 }
34517 }
34518 }
34519
34520 if (!options.olNavigation) {
34521 this.map.zoomSlider = new MapZoomSlider(this.map, "vertical");
34522 this.container.appendChild(this.map.zoomSlider.div);
34523 this.map.zoomSlider.div.style.left = "20px";
34524 }
34525
34526 if (options.resetMap) {
34527 this.homeButton = document.createElement("div");
34528 this.homeButton.setAttribute('class', 'mapHome');
34529 this.homeButton.title = GeoTemConfig.getString('home');
34530 this.container.appendChild(this.homeButton);
34531 this.homeButton.style.left = "20px";
34532 this.homeButton.onclick = function() {
34533 if (map.mds.getAllObjects() == null){
34534 map.openlayersMap.setCenter(new OpenLayers.LonLat(0, 0));
34535 map.openlayersMap.zoomTo(0);
34536 }
34537 gui.map.drawObjectLayer(true);
34538 }
34539 }
34540
34541 if (options.legend) {
34542 this.legendDiv = document.createElement("div");
34543 this.legendDiv.setAttribute('class', 'mapLegend');
34544 this.mapWindow.appendChild(this.legendDiv);
34545 }
34546
34547 var linkForOsm = 'http://www.openstreetmap.org/';
34548 var linkForLicense = 'http://creativecommons.org/licenses/by-sa/2.0/';
34549 this.osmLink = document.createElement("div");
34550 this.osmLink.setAttribute('class', 'osmLink');
34551 this.osmLink.innerHTML = '(c) <a href=' + linkForOsm + '>OpenStreetMap contributors</a>, <a href=' + linkForLicense + '>CC-BY-SA</a>';
34552 this.mapWindow.appendChild(this.osmLink);
34553 this.osmMapQuestLink = document.createElement("div");
34554 this.osmMapQuestLink.setAttribute('class', 'osmLink');
34555 this.osmMapQuestLink.innerHTML = '(c) Data, imagery and map information provided by MapQuest <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png"> <a href=' + linkForOsm + '>OpenStreetMap contributors</a>, <a href=' + linkForLicense + '>CC-BY-SA</a>';
34556 this.mapWindow.appendChild(this.osmMapQuestLink);
34557
34558 // var tooltip = document.createElement("div");
34559 // tooltip.setAttribute('class','ddbTooltip');
34560 // toolbarTable.appendChild(tooltip);
34561
34562 // var tooltip = document.createElement("div");
34563 // tooltip.setAttribute('class','ddbTooltip');
34564 // toolbarTable.appendChild(tooltip);
34565 //
34566 // tooltip.onmouseover = function(){
34567 // /*
34568 // Publisher.Publish('TooltipContent', {
34569 // content: GeoTemConfig.getString(GeoTemConfig.language,'timeHelp'),
34570 // target: $(tooltip)
34571 // });
34572 // */
34573 // }
34574 // tooltip.onmouseout = function(){
34575 // // Publisher.Publish('TooltipContent');
34576 // }
34577 // //vhz tooltip on click should open a help file if defined in GeoTemConfig
34578 // if(GeoTemConfig.helpURL) {
34579 // tooltip.onclick = function () {
34580 //
34581 // }
34582 // }
34583
34584 // }
34585 // tooltip.onmouseout = function(){
34586 // Publisher.Publish('TooltipContent');
34587 // }
34588
34589 this.resize = function() {
34590 var w = this.container.offsetWidth;
34591 var h = this.container.offsetHeight;
34592 // this.mapWindow.style.width = w + "px";
34593 this.mapWindow.style.height = h + "px";
34594 // this.mapContainer.style.width = w + "px";
34595 this.mapContainer.style.height = h + "px";
34596 var top = toolbarTable.offsetHeight + 20;
34597 if (options.olLayerSwitcher) {
34598 var switcherDiv = $('.olControlLayerSwitcher')[0];
34599 $(switcherDiv).css('top', top + "px");
34600 }
34601 if ( typeof this.geoLocation != "undefined") {
34602 this.geoLocation.style.top = top + "px";
34603 top += this.geoLocation.offsetHeight + 4;
34604 }
34605 if (options.olNavigation) {
34606 var panZoomBar = $('.olControlPanZoom')[0];
34607 $(panZoomBar).css('top', top + 'px');
34608 $(panZoomBar).css('left', '12px');
34609 var zoomOut = document.getElementById('OpenLayers.Control.PanZoom_23_zoomout');
34610 top += $(zoomOut).height() + $(zoomOut).position().top + 4;
34611 } else {
34612 this.map.zoomSlider.div.style.top = top + "px";
34613 top += this.map.zoomSlider.div.offsetHeight + 2;
34614 }
34615 if (options.resetMap) {
34616 this.homeButton.style.top = top + "px";
34617 }
34618 this.headerHeight = toolbarTable.offsetHeight;
34619 this.headerWidth = toolbarTable.offsetWidth;
34620 this.map.openlayersMap.updateSize();
34621 this.map.drawObjectLayer(true);
34622 };
34623
34624 this.updateLegend = function(datasets){
34625 $(this.legendDiv).empty();
34626 var table = $('<table style="margin:10px"/>').appendTo(this.legendDiv);
34627 for( var i=0; i<datasets.length; i++ ){
34628 var row = $('<tr/>').appendTo(table);
34629 if( options.useGraphics ){
34630 var graphic = map.config.getGraphic(i);
34631 var fill = 'rgb(' + graphic.color.r0 + ',' + graphic.color.g0 + ',' + graphic.color.b0 + ')';
34632 var stroke = 'rgb(' + graphic.color.r1 + ',' + graphic.color.g1 + ',' + graphic.color.b1 + ')';
34633 var rot = graphic.rotation;
34634 var svg;
34635 if( graphic.shape == 'circle' ){
34636 svg = '<svg style="width:20px;height:20px;"><circle cx="10" cy="10" r="7" stroke="'+stroke+'" stroke-width="2" fill="'+fill+'"/></svg>';
34637 }
34638 else if( graphic.shape == 'square' ){
34639 svg = '<svg style="width:20px;height:20px;"><polygon points="4,4 16,4 16,16 4,16" style="fill:'+fill+';stroke:'+stroke+';stroke-width:2" transform="rotate('+rot+' 10,10)"/></svg>';
34640 }
34641 else if( graphic.shape == 'triangle' ){
34642 svg = '<svg style="width:20px;height:20px;"><polygon points="3,17 17,17 10,5" style="fill:'+fill+';stroke:'+stroke+';stroke-width:2" transform="rotate('+rot+' 10,10)"/></svg>';
34643 }
34644 $('<td>'+svg+'</td>').appendTo(row);
34645 }
34646 else {
34647 var c = GeoTemConfig.getColor(i);
34648 var fill = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
34649 var stroke = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
34650 var svg = '<svg style="width:20px;height:20px;"><circle cx="10" cy="10" r="7" stroke="'+stroke+'" stroke-width="2" fill="'+fill+'"/></svg>';
34651 $('<td>'+svg+'</td>').appendTo(row);
34652 }
34653 $('<td>'+datasets[i].label+'</td>').appendTo(row);
34654 }
34655 };
34656
34657 this.updateSpaceQuantity = function(count) {
34658 if (!options.dataInformation) {
34659 return;
34660 }
34661 this.mapCount = count;
34662 if (count != 1) {
34663 this.mapElements.innerHTML = this.beautifyCount(count) + " " + GeoTemConfig.getString('results');
34664 } else {
34665 this.mapElements.innerHTML = this.beautifyCount(count) + " " + GeoTemConfig.getString('result');
34666 }
34667 }
34668
34669 this.setMapsDropdown = function() {
34670 if (!options.mapSelection) {
34671 return;
34672 }
34673 $(this.mapTypeSelector).empty();
34674 var maps = [];
34675 var gui = this;
34676 var addMap = function(name, index) {
34677 var setMap = function() {
34678 gui.map.setMap(index);
34679 }
34680 maps.push({
34681 name : name,
34682 onclick : setMap
34683 });
34684 }
34685 for (var i = 0; i < this.map.baseLayers.length; i++) {
34686 addMap(this.map.baseLayers[i].name, i);
34687 }
34688 this.mapTypeDropdown = new Dropdown(this.mapTypeSelector, maps, GeoTemConfig.getString('selectMapType'));
34689 }
34690
34691 this.setMap = function() {
34692 if (options.mapSelection) {
34693 this.mapTypeDropdown.setEntry(this.map.baselayerIndex);
34694 }
34695 }
34696
34697 this.setBinningDropdown = function() {
34698 if (!options.binningSelection) {
34699 return;
34700 }
34701 $(this.binningSelector).empty();
34702 var binnings = [];
34703 var gui = this;
34704 var index = 0;
34705 var entry;
34706 var addBinning = function(name, id) {
34707 if (options.binning == id) {
34708 entry = index;
34709 } else {
34710 index++;
34711 }
34712 var setBinning = function() {
34713 options.binning = id;
34714 gui.map.initWidget(gui.map.datasets, false);
34715 gui.map.riseLayer();
34716 }
34717 binnings.push({
34718 name : name,
34719 onclick : setBinning
34720 });
34721 }
34722 addBinning(GeoTemConfig.getString('genericBinning'), 'generic');
34723 addBinning(GeoTemConfig.getString('squareBinning'), 'square');
34724 addBinning(GeoTemConfig.getString('hexagonalBinning'), 'hexagonal');
34725 addBinning(GeoTemConfig.getString('triangularBinning'), 'triangular');
34726 addBinning(GeoTemConfig.getString('noBinning'), false);
34727 var binningDropdown = new Dropdown(this.binningSelector, binnings, GeoTemConfig.getString('binningTooltip'));
34728 binningDropdown.setEntry(entry);
34729 }
34730 this.setBinningDropdown();
34731
34732 this.beautifyCount = function(count) {
34733 var c = count + '';
34734 var p = 0;
34735 var l = c.length;
34736 while (l - p > 3) {
34737 p += 3;
34738 c = c.substring(0, l - p) + "." + c.substring(l - p);
34739 p++;
34740 l++;
34741 }
34742 return c;
34743 }
34744
34745 };
34746 /*
34747 * MapWidget.js
34748 *
34749 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
34750 *
34751 * This library is free software; you can redistribute it and/or
34752 * modify it under the terms of the GNU Lesser General Public
34753 * License as published by the Free Software Foundation; either
34754 * version 3 of the License, or (at your option) any later version.
34755 *
34756 * This library is distributed in the hope that it will be useful,
34757 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34758 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34759 * Lesser General Public License for more details.
34760 *
34761 * You should have received a copy of the GNU Lesser General Public
34762 * License along with this library; if not, write to the Free Software
34763 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
34764 * MA 02110-1301 USA
34765 */
34766
34767 /**
34768 * @class MapWidget
34769 * MapWidget Implementation
34770 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
34771 * @release 1.0
34772 * @release date: 2012-07-27
34773 * @version date: 2012-07-27
34774 *
34775 * @param {MapWrapper} core wrapper for interaction to other widgets
34776 * @param {HTML object} div parent div to append the map widget div
34777 * @param {JSON} options user specified configuration that overwrites options in MapConfig.js
34778 */
34779 MapWidget = function(core, div, options) {
34780
34781 this.core = core;
34782 this.core.setWidget(this);
34783 this.openlayersMap
34784 this.baseLayers
34785 this.objectLayer
34786
34787 this.drawPolygon
34788 this.drawCircle
34789 this.selectCountry
34790 this.dragArea
34791 this.selectFeature
34792 this.navigation
34793
34794 this.div = div;
34795
34796 this.iid = GeoTemConfig.getIndependentId('map');
34797 this.config = new MapConfig(options);
34798 this.options = this.config.options;
34799 this.formerCP = this.options.circlePackings;
34800 this.gui = new MapGui(this, this.div, this.options, this.iid);
34801
34802 this.initialize();
34803
34804 }
34805
34806 MapWidget.prototype = {
34807
34808 /**
34809 * initializes the map for the Spatio Temporal Interface.
34810 * it includes setting up all layers of the map and defines all map specific interaction possibilities
34811 */
34812 initialize : function() {
34813
34814 var map = this;
34815
34816 //OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
34817 if (map.options.proxyHost) {
34818 OpenLayers.ProxyHost = map.options.proxyHost;
34819 }
34820
34821 this.polygons = [];
34822 this.connections = [];
34823 this.selection = new Selection();
34824 this.wmsOverlays = [];
34825
34826 this.layerZIndex = 1;
34827 this.zIndices = [];
34828
34829 var activateDrag = function() {
34830 map.dragArea.activate();
34831 }
34832 var deactivateDrag = function() {
34833 map.dragArea.deactivate();
34834 }
34835 this.dragControl = new MapControl(this, null, 'drag', activateDrag, deactivateDrag);
34836
34837 /*
34838 this.editPolygon = document.createElement("div");
34839 this.editPolygon.title = GeoTemConfig.getString('editPolygon');
34840 this.editPolygon.setAttribute('class','editMapPolygon');
34841 this.toolbar.appendChild(this.editPolygon);
34842 this.drag.onclick = function(evt){
34843 if( map.activeControl == "drag" ){
34844 map.deactivate("drag");
34845 if( GeoTemConfig.navigate ){
34846 map.activate("navigate");
34847 }
34848 }
34849 else {
34850 map.deactivate(map.activControl);
34851 map.activate("drag");
34852 }
34853 }
34854 map.addEditingMode(new OpenLayers.Control.EditingMode.PointArraySnapping());
34855 */
34856
34857 this.filterBar = new FilterBar(this, this.gui.filterOptions);
34858
34859 this.objectLayer = new OpenLayers.Layer.Vector("Data Objects", {
34860 projection : "EPSG:4326",
34861 'displayInLayerSwitcher' : false,
34862 rendererOptions : {
34863 zIndexing : true
34864 }
34865 });
34866
34867 this.markerLayer = new OpenLayers.Layer.Markers("Markers");
34868
34869 this.navigation = new OpenLayers.Control.Navigation({
34870 zoomWheelEnabled : GeoTemConfig.mouseWheelZoom
34871 });
34872 this.navigation.defaultDblClick = function(evt) {
34873 var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
34874 this.map.setCenter(newCenter, this.map.zoom + 1);
34875 map.drawObjectLayer(false);
34876 if (map.zoomSlider) {
34877 map.zoomSlider.setValue(map.getZoom());
34878 }
34879 }
34880 this.navigation.wheelUp = function(evt) {
34881 this.wheelChange(evt, 1);
34882 }
34883 this.navigation.wheelDown = function(evt) {
34884 this.wheelChange(evt, -1);
34885 }
34886
34887 this.resolutions = [78271.516953125, 39135.7584765625, 19567.87923828125, 9783.939619140625, 4891.9698095703125, 2445.9849047851562, 1222.9924523925781, 611.4962261962891, 305.74811309814453, 152.87405654907226, 76.43702827453613, 38.218514137268066, 19.109257068634033, 9.554628534317017, 4.777314267158508, 2.388657133579254, 1.194328566789627, 0.5971642833948135, 0.29858214169740677];
34888
34889 var options = {
34890 controls : [this.navigation],
34891 projection : new OpenLayers.Projection("EPSG:900913"),
34892 displayProjection : new OpenLayers.Projection("EPSG:4326"),
34893 resolutions : this.resolutions,
34894 units : 'meters',
34895 maxExtent : new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)
34896 };
34897 this.openlayersMap = new OpenLayers.Map("mapContainer"+this.iid, options);
34898 if (map.options.navigate) {
34899 this.activeControl = "navigate";
34900 }
34901 //add attribution control
34902 this.openlayersMap.addControl(new OpenLayers.Control.Attribution());
34903 this.mds = new MapDataSource(this, this.options);
34904
34905 //on zoomend, redraw objects and set slider (if it exists) accordingly (zoom by mouse wheel)
34906 this.openlayersMap.events.register("zoomend", map, function(){
34907 map.drawObjectLayer(false);
34908 if (map.zoomSlider) {
34909 map.zoomSlider.setValue(map.getZoom());
34910 }
34911 map.core.triggerHighlight([]);
34912 });
34913
34914 if (map.options.olNavigation) {
34915 var zoomPanel = new OpenLayers.Control.PanZoom();
34916 zoomPanel.onButtonClick = function(evt) {
34917 var btn = evt.buttonElement;
34918 switch (btn.action) {
34919 case "panup":
34920 this.map.pan(0, -this.getSlideFactor("h"));
34921 break;
34922 case "pandown":
34923 this.map.pan(0, this.getSlideFactor("h"));
34924 break;
34925 case "panleft":
34926 this.map.pan(-this.getSlideFactor("w"), 0);
34927 break;
34928 case "panright":
34929 this.map.pan(this.getSlideFactor("w"), 0);
34930 break;
34931 case "zoomin":
34932 map.zoom(1);
34933 break;
34934 case "zoomout":
34935 map.zoom(-1);
34936 break;
34937 case "zoomworld":
34938 if (this.map) {
34939 map.zoom(this.map.zoom * -1);
34940 }
34941 break;
34942 }
34943 };
34944 this.openlayersMap.addControl(zoomPanel);
34945 }
34946
34947 if (map.options.popups) {
34948 var panMap = function() {
34949 if (map.selectedGlyph) {
34950 var lonlat = new OpenLayers.LonLat(map.selectedGlyph.lon, map.selectedGlyph.lat);
34951 var pixel = map.openlayersMap.getPixelFromLonLat(lonlat);
34952 if (map.popup) {
34953 map.popup.shift(pixel.x, pixel.y);
34954 }
34955 }
34956 }
34957 this.openlayersMap.events.register("move", this.openlayersMap, panMap);
34958 }
34959
34960 if (map.options.olMapOverview) {
34961 this.openlayersMap.addControl(new OpenLayers.Control.OverviewMap());
34962 }
34963 if (map.options.olKeyboardDefaults) {
34964 var keyboardControl = new OpenLayers.Control.KeyboardDefaults();
34965 keyboardControl.defaultKeyPress = function(evt) {
34966 switch(evt.keyCode) {
34967 case OpenLayers.Event.KEY_LEFT:
34968 this.map.pan(-this.slideFactor, 0);
34969 break;
34970 case OpenLayers.Event.KEY_RIGHT:
34971 this.map.pan(this.slideFactor, 0);
34972 break;
34973 case OpenLayers.Event.KEY_UP:
34974 this.map.pan(0, -this.slideFactor);
34975 break;
34976 case OpenLayers.Event.KEY_DOWN:
34977 this.map.pan(0, this.slideFactor);
34978 break;
34979
34980 case 33:
34981 // Page Up. Same in all browsers.
34982 var size = this.map.getSize();
34983 this.map.pan(0, -0.75 * size.h);
34984 break;
34985 case 34:
34986 // Page Down. Same in all browsers.
34987 var size = this.map.getSize();
34988 this.map.pan(0, 0.75 * size.h);
34989 break;
34990 case 35:
34991 // End. Same in all browsers.
34992 var size = this.map.getSize();
34993 this.map.pan(0.75 * size.w, 0);
34994 break;
34995 case 36:
34996 // Home. Same in all browsers.
34997 var size = this.map.getSize();
34998 this.map.pan(-0.75 * size.w, 0);
34999 break;
35000
35001 case 43:
35002 // +/= (ASCII), keypad + (ASCII, Opera)
35003 case 61:
35004 // +/= (Mozilla, Opera, some ASCII)
35005 case 187:
35006 // +/= (IE)
35007 case 107:
35008 // keypad + (IE, Mozilla)
35009 map.zoom(1);
35010 break;
35011 case 45:
35012 // -/_ (ASCII, Opera), keypad - (ASCII, Opera)
35013 case 109:
35014 // -/_ (Mozilla), keypad - (Mozilla, IE)
35015 case 189:
35016 // -/_ (IE)
35017 case 95:
35018 // -/_ (some ASCII)
35019 map.zoom(-1);
35020 break;
35021 }
35022 };
35023 this.openlayersMap.addControl(keyboardControl);
35024 }
35025 if (map.options.olLayerSwitcher) {
35026 this.openlayersMap.addControl(new OpenLayers.Control.LayerSwitcher());
35027 }
35028 if (map.options.olScaleLine) {
35029 this.openlayersMap.addControl(new OpenLayers.Control.ScaleLine());
35030 }
35031 this.gui.resize();
35032 this.setBaseLayers();
35033 this.gui.setMapsDropdown();
35034 this.gui.setMap();
35035 this.openlayersMap.addLayers([this.objectLayer, this.markerLayer]);
35036
35037 if (map.options.boundaries) {
35038 var boundaries = map.options.boundaries;
35039 var bounds = new OpenLayers.Bounds(boundaries.minLon, boundaries.minLat, boundaries.maxLon, boundaries.maxLat);
35040 var projectionBounds = bounds.transform(this.openlayersMap.displayProjection, this.openlayersMap.projection);
35041 this.openlayersMap.zoomToExtent(projectionBounds);
35042 } else {
35043 this.openlayersMap.zoomToMaxExtent();
35044 }
35045
35046 // manages selection of elements if a polygon was drawn
35047 this.drawnPolygonHandler = function(polygon) {
35048 if (map.mds.getAllObjects() == null) {
35049 return;
35050 }
35051 var polygonFeature;
35052 if ( polygon instanceof OpenLayers.Geometry.Polygon) {
35053 polygonFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon([polygon]));
35054 } else if ( polygon instanceof OpenLayers.Geometry.MultiPolygon) {
35055 polygonFeature = new OpenLayers.Feature.Vector(polygon);
35056 }
35057 map.polygons.push(polygonFeature);
35058 var style = $.extend(true, {}, OpenLayers.Feature.Vector.style['default']);
35059 style.graphicZIndex = 0;
35060 polygonFeature.style = style;
35061 map.objectLayer.addFeatures([polygonFeature]);
35062 try {
35063 map.activeControl.deactivate();
35064 } catch(e) {
35065 }
35066 var circles = map.mds.getObjectsByZoom();
35067 for (var i = 0; i < circles.length; i++) {
35068 for (var j = 0; j < circles[i].length; j++) {
35069 var c = circles[i][j];
35070 if (map.inPolygon(c)) {
35071 if ( typeof c.fatherBin != 'undefined') {
35072 for (var k = 0; k < c.fatherBin.circles.length; k++) {
35073 if (c.fatherBin.circles[k]) {
35074 c.fatherBin.circles[k].setSelection(true);
35075 }
35076 }
35077 } else {
35078 c.setSelection(true);
35079 }
35080 }
35081 }
35082 }
35083 map.mapSelection();
35084 }
35085
35086 this.polygonDeselection = function() {
35087 var circles = map.mds.getObjectsByZoom();
35088 for (var i = 0; i < circles.length; i++) {
35089 for (var j = 0; j < circles[i].length; j++) {
35090 var c = circles[i][j];
35091 if (map.inPolygon(c)) {
35092 c.setSelection(false);
35093 }
35094 }
35095 }
35096 }
35097 this.snapper = function() {
35098 if (map.polygons.length == 0 || !map.options.multiSelection) {
35099 map.deselection();
35100 }
35101 }
35102 if (map.options.polygonSelect) {
35103 this.drawPolygon = new OpenLayers.Control.DrawFeature(map.objectLayer, OpenLayers.Handler.Polygon, {
35104 displayClass : "olControlDrawFeaturePolygon",
35105 callbacks : {
35106 "done" : map.drawnPolygonHandler,
35107 "create" : map.snapper
35108 }
35109 });
35110 this.openlayersMap.addControl(this.drawPolygon);
35111 }
35112
35113 if (map.options.circleSelect) {
35114 this.drawCircle = new OpenLayers.Control.DrawFeature(map.objectLayer, OpenLayers.Handler.RegularPolygon, {
35115 displayClass : "olControlDrawFeaturePolygon",
35116 handlerOptions : {
35117 sides : 40
35118 },
35119 callbacks : {
35120 "done" : map.drawnPolygonHandler,
35121 "create" : map.snapper
35122 }
35123 });
35124 this.openlayersMap.addControl(this.drawCircle);
35125 }
35126
35127 if (map.options.squareSelect) {
35128 this.drawSquare = new OpenLayers.Control.DrawFeature(map.objectLayer, OpenLayers.Handler.RegularPolygon, {
35129 displayClass : "olControlDrawFeaturePolygon",
35130 handlerOptions : {
35131 sides : 4,
35132 irregular: true
35133 },
35134 callbacks : {
35135 "done" : map.drawnPolygonHandler,
35136 "create" : map.snapper
35137 }
35138 });
35139 this.openlayersMap.addControl(this.drawSquare);
35140 }
35141
35142 if (map.options.polygonSelect || map.options.circleSelect || map.options.squareSelect) {
35143 this.dragArea = new OpenLayers.Control.DragFeature(map.objectLayer, {
35144 onStart : function(feature) {
35145 feature.style.graphicZIndex = 10000;
35146 map.polygonDeselection();
35147 },
35148 onComplete : function(feature) {
35149 feature.style.graphicZIndex = 0;
35150 map.drawnPolygonHandler(feature.geometry);
35151 }
35152 });
35153 this.openlayersMap.addControl(this.dragArea);
35154
35155 this.modifyArea = new OpenLayers.Control.ModifyFeature(map.objectLayer, {
35156 onStart : function(feature) {
35157 feature.style.graphicZIndex = 10000;
35158 map.polygonDeselection();
35159 },
35160 onComplete : function(feature) {
35161 feature.style.graphicZIndex = 0;
35162 map.drawnPolygonHandler(feature.geometry);
35163 }
35164 });
35165 this.openlayersMap.addControl(this.modifyArea);
35166 this.modifyArea.mode = OpenLayers.Control.ModifyFeature.RESHAPE;
35167
35168 }
35169
35170 // calculates the tag cloud
35171 // manages hover selection of point objects
35172 var hoverSelect = function(event) {
35173 var object = event.feature;
35174 if (object.geometry instanceof OpenLayers.Geometry.Point) {
35175 if ( typeof map.placenameTags != 'undefined') {
35176 map.placenameTags.remove();
35177 }
35178 var circle = event.feature.parent;
35179 if ( circle instanceof CircleObject) {
35180 circle.placenameTags = new PlacenameTags(circle, map);
35181 map.placenameTags = circle.placenameTags;
35182 } else {
35183 return;
35184 /*
35185 event.feature.style.fillOpacity = 0.2;
35186 event.feature.style.strokeOpacity = 1;
35187 map.objectLayer.drawFeature(event.feature);
35188 circle.placenameTags = new PackPlacenameTags(circle,map);
35189 */
35190 }
35191 circle.placenameTags.calculate();
35192 map.mapCircleHighlight(object.parent, false);
35193 if ( typeof map.featureInfo != 'undefined') {
35194 map.featureInfo.deactivate();
35195 }
35196 } else {
35197 map.dragControl.checkStatus();
35198 }
35199 };
35200 var hoverUnselect = function(event) {
35201 var object = event.feature;
35202 if (object.geometry instanceof OpenLayers.Geometry.Point) {
35203 var circle = event.feature.parent;
35204 if (!( circle instanceof CircleObject )) {
35205 return;
35206 /*
35207 event.feature.style.fillOpacity = 0;
35208 event.feature.style.strokeOpacity = 0;
35209 map.objectLayer.drawFeature(event.feature);
35210 */
35211 }
35212 circle.placenameTags.remove();
35213 map.mapCircleHighlight(object.parent, true);
35214 if ( typeof map.featureInfo != 'undefined') {
35215 map.featureInfo.activate();
35216 }
35217 } else {
35218 map.dragControl.deactivate();
35219 }
35220 };
35221 var highlightCtrl = new OpenLayers.Control.SelectFeature(this.objectLayer, {
35222 hover : true,
35223 highlightOnly : true,
35224 renderIntent : "temporary",
35225 eventListeners : {
35226 featurehighlighted : hoverSelect,
35227 featureunhighlighted : hoverUnselect
35228 }
35229 });
35230 this.openlayersMap.addControl(highlightCtrl);
35231 highlightCtrl.activate();
35232
35233 this.selectFeature = new OpenLayers.Control.SelectFeature(this.objectLayer);
35234
35235 document.onkeydown = function(e) {
35236 if (e.ctrlKey) {
35237 map.ctrlKey = true;
35238 }
35239 }
35240 document.onkeyup = function(e) {
35241 map.ctrlKey = false;
35242 }
35243 // manages click selection of point objects
35244 var onFeatureSelect = function(event, evt) {
35245 if (!(event.feature.geometry instanceof OpenLayers.Geometry.Point)) {
35246 return;
35247 }
35248 var circle = event.feature.parent;
35249 if (map.options.multiSelection && map.ctrlKey) {
35250 if (map.popup) {
35251 map.popup.reset();
35252 map.selectedGlyph = false;
35253 }
35254 circle.toggleSelection();
35255 map.mapSelection();
35256 return;
35257 }
35258 map.reset();
35259 circle.setSelection(true);
35260 map.objectLayer.drawFeature(circle.feature);
35261 if (map.options.popups) {
35262 if (map.popup) {
35263 map.popup.reset();
35264 }
35265 var lonlat = event.feature.geometry.getBounds().getCenterLonLat();
35266 var pixel = map.openlayersMap.getPixelFromLonLat(lonlat);
35267 map.selectedGlyph = {
35268 lon : lonlat.lon,
35269 lat : lonlat.lat
35270 };
35271 map.popup = new PlacenamePopup(map);
35272 map.popup.createPopup(pixel.x, pixel.y, circle.placenameTags.placeLabels);
35273 if (map.options.selectDefault) {
35274 circle.placenameTags.selectLabel();
35275 }
35276 }
35277 }
35278 this.objectLayer.events.on({
35279 "featureselected" : onFeatureSelect
35280 });
35281
35282 this.openlayersMap.addControl(this.selectFeature);
35283 this.selectFeature.activate();
35284
35285 if (this.zoomSlider) {
35286 this.zoomSlider.setMaxAndLevels(1000, this.openlayersMap.getNumZoomLevels());
35287 this.zoomSlider.setValue(this.getZoom());
35288 }
35289
35290 Publisher.Subscribe('mapChanged', this, function(mapName) {
35291 this.client.setBaseLayerByName(mapName);
35292 this.client.gui.setMap();
35293 });
35294
35295 },
35296
35297 shift : function(shiftX, shiftY) {
35298 this.openlayersMap.pan(shiftX, shiftY);
35299 },
35300
35301 addBaseLayers : function(layers) {
35302 if ( layers instanceof Array) {
35303 for (var i in layers ) {
35304 var layer;
35305 if (layers[i].type === "XYZ"){
35306 layer = new OpenLayers.Layer.XYZ(
35307 layers[i].name,
35308 [
35309 layers[i].url
35310 ],
35311 {
35312 sphericalMercator: true,
35313 transitionEffect: "resize",
35314 buffer: 1,
35315 numZoomLevels: 12,
35316 transparent : true,
35317 attribution: layers[i].attribution
35318 },
35319 {
35320 isBaseLayer : true
35321 }
35322 );
35323 } else {
35324 layer = new OpenLayers.Layer.WMS(
35325 layers[i].name, layers[i].url,
35326 {
35327 projection : "EPSG:4326",
35328 layers : layers[i].layer,
35329 transparent : "true",
35330 format : "image/png"
35331 },
35332 {
35333 attribution: layers[i].attribution,
35334 isBaseLayer : true
35335 }
35336 );
35337 }
35338 this.baseLayers.push(layer);
35339 this.openlayersMap.addLayers([layer]);
35340 }
35341 }
35342 this.gui.setMapsDropdown();
35343 },
35344
35345 /**
35346 * set online available maps for Google, Bing and OSM
35347 */
35348 setBaseLayers : function() {
35349 this.baseLayers = [];
35350 if (this.options.googleMaps) {
35351 // see http://openlayers.org/blog/2010/07/10/google-maps-v3-for-openlayers/ for information
35352 var gphy = new OpenLayers.Layer.Google("Google Physical", {
35353 type : google.maps.MapTypeId.TERRAIN,
35354 minZoomLevel : 1,
35355 maxZoomLevel : 19
35356 });
35357 var gmap = new OpenLayers.Layer.Google("Google Streets", {
35358 minZoomLevel : 1,
35359 maxZoomLevel : 19
35360 });
35361 var ghyb = new OpenLayers.Layer.Google("Google Hybrid", {
35362 type : google.maps.MapTypeId.HYBRID,
35363 minZoomLevel : 1,
35364 maxZoomLevel : 19
35365 });
35366 var gsat = new OpenLayers.Layer.Google("Google Satellite", {
35367 type : google.maps.MapTypeId.SATELLITE,
35368 minZoomLevel : 1,
35369 maxZoomLevel : 19
35370 });
35371 this.baseLayers.push(gphy);
35372 this.baseLayers.push(gmap);
35373 this.baseLayers.push(ghyb);
35374 this.baseLayers.push(gsat);
35375 }
35376 if (this.options.bingMaps) {
35377 // see http://openlayers.org/blog/2010/12/18/bing-tiles-for-openlayers/ for information
35378 var apiKey = this.options.bingApiKey;
35379 var road = new OpenLayers.Layer.Bing({
35380 name : "Road",
35381 key : apiKey,
35382 type : "Road"
35383 });
35384 var hybrid = new OpenLayers.Layer.Bing({
35385 name : "Hybrid",
35386 key : apiKey,
35387 type : "AerialWithLabels"
35388 });
35389 var aerial = new OpenLayers.Layer.Bing({
35390 name : "Aerial",
35391 key : apiKey,
35392 type : "Aerial"
35393 });
35394 this.baseLayers.push(road);
35395 this.baseLayers.push(hybrid);
35396 this.baseLayers.push(aerial);
35397 }
35398 if (this.options.osmMaps) {
35399 this.baseLayers.push(new OpenLayers.Layer.OSM('Open Street Map', '', {
35400 sphericalMercator : true,
35401 zoomOffset : 1,
35402 resolutions : this.resolutions
35403 }));
35404 }
35405 if (this.options.osmMapsMapQuest) {
35406 this.baseLayers.push(new OpenLayers.Layer.OSM('Open Street Map (MapQuest)',
35407 ["http://otile1.mqcdn.com/tiles/1.0.0/map/${z}/${x}/${y}.png",
35408 "http://otile2.mqcdn.com/tiles/1.0.0/map/${z}/${x}/${y}.png",
35409 "http://otile3.mqcdn.com/tiles/1.0.0/map/${z}/${x}/${y}.png",
35410 "http://otile4.mqcdn.com/tiles/1.0.0/map/${z}/${x}/${y}.png"],
35411 {
35412 sphericalMercator : true,
35413 zoomOffset : 1,
35414 resolutions : this.resolutions
35415 }
35416 ));
35417 }
35418 for (var i = 0; i < this.baseLayers.length; i++) {
35419 this.openlayersMap.addLayers([this.baseLayers[i]]);
35420 }
35421 if (this.options.alternativeMap) {
35422 if (!(this.options.alternativeMap instanceof Array))
35423 this.options.alternativeMap = [this.options.alternativeMap];
35424 this.addBaseLayers(this.options.alternativeMap);
35425 }
35426 this.setBaseLayerByName(this.options.baseLayer);
35427 },
35428
35429 setBaseLayerByName : function(name){
35430 for (var i = 0; i < this.baseLayers.length; i++) {
35431 if (this.baseLayers[i].name == name) {
35432 this.setMap(i);
35433 }
35434 }
35435 },
35436
35437 getBaseLayerName : function() {
35438 return this.openlayersMap.baseLayer.name;
35439 },
35440
35441 setOverlays : function(layers) {
35442 var map = this;
35443 for (var i in this.wmsOverlays ) {
35444 this.openlayersMap.removeLayer(this.wmsOverlays[i]);
35445 }
35446 this.wmsOverlays = [];
35447 var featureInfoLayers = [];
35448 if ( layers instanceof Array) {
35449 for (var i in layers ) {
35450 var layer = new OpenLayers.Layer.WMS(layers[i].name, layers[i].url, {
35451 projection : "EPSG:4326",
35452 layers : layers[i].layer,
35453 transparent : "true",
35454 format : "image/png"
35455 }, {
35456 isBaseLayer : false,
35457 visibility : map.options.overlayVisibility
35458 });
35459 this.wmsOverlays.push(layer);
35460 if (layers[i].featureInfo) {
35461 featureInfoLayers.push(layer);
35462 }
35463 }
35464 this.openlayersMap.addLayers(this.wmsOverlays);
35465 }
35466 if (this.wmsOverlays.length > 0 && map.options.overlayVisibility) {
35467 var map = this;
35468 if ( typeof this.featureInfo != 'undefined') {
35469 this.featureInfo.deactivate();
35470 this.openlayersMap.removeControl(this.featureInfo);
35471 }
35472 this.featureInfo = new OpenLayers.Control.WMSGetFeatureInfo({
35473 url : '/geoserver/wms',
35474 layers : featureInfoLayers,
35475 eventListeners : {
35476 getfeatureinfo : function(event) {
35477 if (event.text == '') {
35478 return;
35479 }
35480 var lonlat = map.openlayersMap.getLonLatFromPixel(new OpenLayers.Pixel(event.xy.x, event.xy.y));
35481 map.selectedGlyph = {
35482 lon : lonlat.lon,
35483 lat : lonlat.lat
35484 };
35485 if ( typeof map.popup != 'undefined') {
35486 map.popup.reset();
35487 }
35488 map.popup = new MapPopup(map);
35489 map.popup.initialize(event.xy.x, event.xy.y);
35490 map.popup.setContent(event.text);
35491 }
35492 }
35493 });
35494 this.openlayersMap.addControl(this.featureInfo);
35495 this.featureInfo.activate();
35496 this.activateCountrySelector(this.wmsOverlays[this.wmsOverlays.length - 1]);
35497 } else {
35498 this.deactivateCountrySelector();
35499 if (this.openlayersMap.baseLayer instanceof OpenLayers.Layer.WMS) {
35500 this.activateCountrySelector(this.openlayersMap.baseLayer);
35501 }
35502 }
35503 },
35504
35505 addBaseLayer : function(layer) {
35506 this.baseLayers.push(layer);
35507 this.openlayersMap.addLayers([layer]);
35508 for (var i in this.baseLayers ) {
35509 if (this.baseLayers[i].name == this.options.baseLayer) {
35510 this.setMap(i);
35511 }
35512 }
35513 },
35514
35515 /**
35516 * draws the object layer.
35517 * @param {boolean} zoom if there was a zoom; if not, the new boundary of the map is calculated
35518 */
35519 drawObjectLayer : function(zoom) {
35520 if ( typeof this.placenameTags != 'undefined') {
35521 this.placenameTags.remove();
35522 }
35523 var points = this.mds.getAllObjects();
35524 if (points == null) {
35525 return;
35526 }
35527 this.objectLayer.removeAllFeatures();
35528
35529 if (zoom) {
35530 var minLat, maxLat, minLon, maxLon;
35531 var pointsHighestZoom = points[points.length - 1];
35532 for (var i = 0; i < pointsHighestZoom.length; i++) {
35533 for (var j = 0; j < pointsHighestZoom[i].length; j++) {
35534 var point = pointsHighestZoom[i][j];
35535 if (minLon == null || point.originX < minLon) {
35536 minLon = point.originX;
35537 }
35538 if (maxLon == null || point.originX > maxLon) {
35539 maxLon = point.originX;
35540 }
35541 if (minLat == null || point.originY < minLat) {
35542 minLat = point.originY;
35543 }
35544 if (maxLat == null || point.originY > maxLat) {
35545 maxLat = point.originY;
35546 }
35547 }
35548 }
35549 if (minLon == maxLon && minLat == maxLat) {
35550 this.openlayersMap.setCenter(new OpenLayers.LonLat(minLon, minLat));
35551 } else {
35552 var gapX = 0.1 * (maxLon - minLon );
35553 var gapY1 = 0.1 * (maxLat - minLat );
35554 var gapY2 = (this.gui.headerHeight / this.gui.mapWindow.offsetHeight + 0.1 ) * (maxLat - minLat );
35555 this.openlayersMap.zoomToExtent(new OpenLayers.Bounds(minLon - gapX, minLat - gapY1, maxLon + gapX, maxLat + gapY2));
35556 this.openlayersMap.zoomTo(Math.floor(this.getZoom()));
35557 }
35558 if (this.zoomSlider) {
35559 this.zoomSlider.setValue(this.getZoom());
35560 }
35561 }
35562 var displayPoints = this.mds.getObjectsByZoom();
35563 var resolution = this.openlayersMap.getResolution();
35564 for (var i = 0; i < displayPoints.length; i++) {
35565 for (var j = 0; j < displayPoints[i].length; j++) {
35566 var p = displayPoints[i][j];
35567 var x = p.originX + resolution * p.shiftX;
35568 var y = p.originY + resolution * p.shiftY;
35569 p.feature.geometry.x = x;
35570 p.feature.geometry.y = y;
35571 p.olFeature.geometry.x = x;
35572 p.olFeature.geometry.y = y;
35573 p.feature.style.graphicZIndex = this.zIndices[i];
35574 p.olFeature.style.graphicZIndex = this.zIndices[i] + 1;
35575 this.objectLayer.addFeatures([p.feature]);
35576 this.objectLayer.addFeatures([p.olFeature]);
35577 }
35578 }
35579 var zoomLevel = this.getZoom();
35580 /*
35581 for (var i = 0; i < this.bins[zoomLevel].length; i++) {
35582 var p = this.bins[zoomLevel][i];
35583 p.feature.style.graphicZIndex = 0;
35584 this.objectLayer.addFeatures([p.feature]);
35585 }
35586 */
35587
35588 var dist = function(p1, p2) {
35589 return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
35590 }
35591
35592 this.highlightChanged(this.selection.getObjects(this.core));
35593
35594 },
35595
35596 riseLayer : function(id) {
35597 this.lastId = id;
35598 if ( typeof id == 'undefined') {
35599 id = this.lastId || 0;
35600 }
35601 this.zIndices[id] = this.layerZIndex;
35602 this.layerZIndex += 2;
35603 this.drawObjectLayer(false);
35604 for( var i=0; i<this.polygons.length; i++ ){
35605 this.objectLayer.addFeatures([this.polygons[i]]);
35606 }
35607 },
35608
35609 /**
35610 * initializes the object layer.
35611 * all point representations for all zoom levels are calculated and initialized
35612 * @param {MapObject[][]} mapObjects an array of map objects from different (1-4) sets
35613 */
35614 initWidget : function(datasets, zoom) {
35615
35616 this.clearMap();
35617
35618 this.datasets = datasets;
35619 var mapObjects = [];
35620 for (var i = 0; i < datasets.length; i++) {
35621 mapObjects.push(datasets[i].objects);
35622 }
35623 if (mapObjects.length > 4) {
35624 this.options.circlePackings = false;
35625 } else {
35626 this.options.circlePackings = this.formerCP;
35627 }
35628
35629 if ( typeof mapObjects == 'undefined') {
35630 return;
35631 }
35632
35633 this.count = 0;
35634 this.objectCount = 0;
35635 for (var i = 0; i < mapObjects.length; i++) {
35636 var c = 0;
35637 for (var j = 0; j < mapObjects[i].length; j++) {
35638 if (mapObjects[i][j].isGeospatial) {
35639 c += mapObjects[i][j].weight;
35640 this.objectCount++;
35641 }
35642 }
35643 this.count += c;
35644 this.zIndices.push(this.layerZIndex);
35645 this.layerZIndex += 2;
35646 }
35647
35648 this.mds.initialize(mapObjects);
35649 var points = this.mds.getAllObjects();
35650 if (points == null) {
35651 return;
35652 }
35653
35654 var getArea = function(radius) {
35655 return Math.PI * radius * radius;
35656 }
35657 for (var i = 0; i < points.length; i++) {
35658 var area = 0;
35659 var maxRadius = 0;
35660 for (var j = 0; j < points[i].length; j++) {
35661 for (var k = 0; k < points[i][j].length; k++) {
35662 if (points[i][j][k].radius > maxRadius) {
35663 maxRadius = points[i][j][k].radius;
35664 area = getArea(maxRadius);
35665 }
35666 }
35667 }
35668 var minArea = getArea(this.options.minimumRadius);
35669 var areaDiff = area - minArea;
35670 for (var j = 0; j < points[i].length; j++) {
35671 for (var k = 0; k < points[i][j].length; k++) {
35672 var point = points[i][j][k];
35673 var c, shape, rotation, multiplier = 1;
35674 if( this.options.useGraphics ){
35675 var graphic = this.config.getGraphic(point.search);
35676 c = graphic.color;
35677 shape = graphic.shape;
35678 rotation = graphic.rotation;
35679 if( shape == 'square' ){
35680 multiplier = 0.75;
35681 }
35682 }
35683 else {
35684 c = GeoTemConfig.getAverageDatasetColor(point.search,point.elements);
35685 shape = 'circle';
35686 rotation = 0;
35687 }
35688 var opacity;
35689 if (this.options.circleOpacity == 'balloon') {
35690 var min = this.options.minTransparency;
35691 var max = this.options.maxTransparency;
35692 opacity = min + Math.abs(min - max) * (1 - (getArea(point.radius) - minArea) / areaDiff);
35693 }
35694 else {
35695 opacity = this.options.circleOpacity;
35696 }
35697 var col = false, ols = 0;
35698 if( this.options.circleOutline ){
35699 col = true;
35700 ols = this.options.circleOutline;
35701 }
35702 var style = {
35703 graphicName: shape,
35704 rotation: rotation,
35705 fillColor : 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')',
35706 fillOpacity : opacity,
35707 strokeWidth : ols,
35708 strokeColor : 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')',
35709 stroke : col,
35710 pointRadius : point.radius * multiplier,
35711 cursor : "pointer"
35712 };
35713 var pointGeometry = new OpenLayers.Geometry.Point(point.originX, point.originY, null);
35714 var feature = new OpenLayers.Feature.Vector(pointGeometry);
35715 feature.style = style;
35716 feature.parent = point;
35717 point.setFeature(feature);
35718 var olStyle = {
35719 graphicName: shape,
35720 rotation: rotation,
35721 fillColor : 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')',
35722 fillOpacity : opacity,
35723 stroke : false,
35724 pointRadius : 0,
35725 cursor : "pointer"
35726 };
35727 var olPointGeometry = new OpenLayers.Geometry.Point(point.originX, point.originY, null);
35728 var olFeature = new OpenLayers.Feature.Vector(olPointGeometry);
35729 olFeature.style = olStyle;
35730 olFeature.parent = point;
35731 point.setOlFeature(olFeature);
35732 }
35733 }
35734 }
35735
35736 /*
35737 this.bins = this.mds.getAllBins();
35738 for (var i = 0; i < this.bins.length; i++) {
35739 for (var j = 0; j < this.bins[i].length; j++) {
35740 var bin = this.bins[i][j];
35741 var style = {
35742 fillColor : 'rgb(140,140,140)',
35743 fillOpacity : 0,
35744 strokeWidth : 2,
35745 strokeOpacity : 0,
35746 strokeColor : 'rgb(140,140,140)',
35747 // stroke: false,
35748 pointRadius : bin.radius,
35749 cursor : "pointer"
35750 };
35751 var pointGeometry = new OpenLayers.Geometry.Point(bin.x, bin.y, null);
35752 var feature = new OpenLayers.Feature.Vector(pointGeometry);
35753 feature.style = style;
35754 feature.parent = bin;
35755 bin.feature = feature;
35756 }
35757 }
35758 */
35759
35760 this.gui.updateLegend(datasets);
35761
35762 if ( typeof zoom == "undefined") {
35763 this.drawObjectLayer(true);
35764 } else {
35765 this.drawObjectLayer(zoom);
35766 }
35767 this.gui.updateSpaceQuantity(this.count);
35768
35769 },
35770
35771 /**
35772 * resets the map by destroying all additional elements except the point objects, which are replaced
35773 */
35774 reset : function() {
35775 if ( typeof this.placenameTags != 'undefined') {
35776 this.placenameTags.remove();
35777 }
35778 this.objectLayer.removeFeatures(this.polygons);
35779 this.polygons = [];
35780 this.objectLayer.removeFeatures(this.connections);
35781 this.connections = [];
35782 this.selectFeature.unselectAll();
35783 this.selectedGlyph = false;
35784 if (this.dragControl.activated) {
35785 this.dragControl.deactivate();
35786 }
35787 if (this.popup) {
35788 this.popup.reset();
35789 }
35790 this.filterBar.reset(false);
35791 var points = this.mds.getObjectsByZoom();
35792 if (points == null) {
35793 return;
35794 }
35795 for (var i = 0; i < points.length; i++) {
35796 for (var j = 0; j < points[i].length; j++) {
35797 points[i][j].setSelection(false);
35798 }
35799 }
35800 },
35801
35802 /**
35803 * resets the map by destroying all elements
35804 */
35805 clearMap : function() {
35806 this.reset();
35807 this.selection = new Selection();
35808 this.zIndices = [];
35809 this.layerZIndex = 1;
35810 this.objectLayer.destroyFeatures();
35811 },
35812
35813 /**
35814 * updates the proportional selection status of a point object
35815 * @param {PointObject} point the point to update
35816 * @param {OpenLayers.Geometry.Polygon} polygon the actual displayed map polygon
35817 */
35818 updatePoint : function(point, polygon) {
35819 var olRadius = this.mds.binning.getRadius(point.overlay);
35820 if( this.options.useGraphics ){
35821 var graphic = this.config.getGraphic(point.search);
35822 if( graphic.shape == 'square' ){
35823 olRadius *= 0.75;
35824 }
35825 }
35826 point.olFeature.style.pointRadius = olRadius;
35827 var c = GeoTemConfig.getAverageDatasetColor(point.search, point.overlayElements);
35828 point.olFeature.style.fillColor = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
35829 if (polygon.containsPoint(point.feature.geometry)) {
35830 this.objectLayer.drawFeature(point.olFeature);
35831 }
35832 },
35833
35834 /**
35835 * updates the the object layer of the map after selections had been executed in timeplot or table or zoom level has changed
35836 */
35837 highlightChanged : function(mapObjects) {
35838 if( !GeoTemConfig.highlightEvents ){
35839 return;
35840 }
35841 this.mds.clearOverlay();
35842 if (this.selection.valid()) {
35843 this.mds.setOverlay(GeoTemConfig.mergeObjects(mapObjects, this.selection.getObjects()));
35844 } else {
35845 this.mds.setOverlay(mapObjects);
35846 }
35847 var points = this.mds.getObjectsByZoom();
35848 var polygon = this.openlayersMap.getExtent().toGeometry();
35849 for (var i in points ) {
35850 for (var j in points[i] ) {
35851 this.updatePoint(points[i][j], polygon);
35852 }
35853 }
35854 this.displayConnections();
35855 },
35856
35857 selectionChanged : function(selection) {
35858 if( !GeoTemConfig.selectionEvents ){
35859 return;
35860 }
35861 this.reset();
35862 this.selection = selection;
35863 this.highlightChanged(selection.objects);
35864 },
35865
35866 inPolygon : function(point) {
35867 for (var i = 0; i < this.polygons.length; i++) {
35868 var polygon = this.polygons[i].geometry;
35869 for (var j = 0; j < polygon.components.length; j++) {
35870 if (polygon.components[j].containsPoint(point.feature.geometry)) {
35871 return true;
35872 }
35873 }
35874 }
35875 return false;
35876 },
35877
35878 mapSelection : function() {
35879 var selectedObjects = [];
35880 for (var i = 0; i < this.mds.size(); i++) {
35881 selectedObjects.push([]);
35882 }
35883 var circles = this.mds.getObjectsByZoom();
35884 for (var i = 0; i < circles.length; i++) {
35885
35886 for (var j = 0; j < circles[i].length; j++) {
35887 var c = circles[i][j];
35888 if (c.selected) {
35889 selectedObjects[i] = selectedObjects[i].concat(c.elements);
35890 }
35891 }
35892 }
35893 this.selection = new Selection(selectedObjects, this);
35894 this.highlightChanged(selectedObjects);
35895 this.core.triggerSelection(this.selection);
35896 this.filterBar.reset(true);
35897 },
35898
35899 deselection : function() {
35900 this.reset();
35901 this.selection = new Selection();
35902 this.highlightChanged([]);
35903 this.core.triggerSelection(this.selection);
35904 },
35905
35906 filtering : function() {
35907 for (var i = 0; i < this.datasets.length; i++) {
35908 this.datasets[i].objects = this.selection.objects[i];
35909 }
35910 this.core.triggerRefining(this.datasets);
35911 },
35912
35913 inverseFiltering : function() {
35914 var selectedObjects = [];
35915 for (var i = 0; i < this.mds.size(); i++) {
35916 selectedObjects.push([]);
35917 }
35918 var circles = this.mds.getObjectsByZoom();
35919 for (var i = 0; i < circles.length; i++) {
35920 for (var j = 0; j < circles[i].length; j++) {
35921 var c = circles[i][j];
35922 if (!c.selected) {
35923 selectedObjects[i] = selectedObjects[i].concat(c.elements);
35924 }
35925 }
35926 }
35927 this.selection = new Selection(selectedObjects, this);
35928 this.filtering();
35929 },
35930
35931 mapCircleHighlight : function(circle, undo) {
35932 if (this.polygons.length > 0 && this.inPolygon(circle)) {
35933 return;
35934 }
35935 var mapObjects = [];
35936 for (var i = 0; i < this.mds.size(); i++) {
35937 mapObjects.push([]);
35938 }
35939 if (!undo && !circle.selected) {
35940 mapObjects[circle.search] = circle.elements;
35941 }
35942 this.objectLayer.drawFeature(circle.feature);
35943 this.core.triggerHighlight(mapObjects);
35944 },
35945
35946 mapLabelSelection : function(label) {
35947 var selectedObjects = [];
35948 for (var i = 0; i < this.mds.size(); i++) {
35949 selectedObjects.push([]);
35950 }
35951 selectedObjects[label.index] = label.elements;
35952 this.selection = new Selection(selectedObjects, this);
35953 this.highlightChanged(selectedObjects);
35954 this.core.triggerSelection(this.selection);
35955 this.filterBar.reset(true);
35956 },
35957
35958 triggerMapChanged : function(mapName) {
35959 Publisher.Publish('mapChanged', mapName, this);
35960 },
35961
35962 /**
35963 * displays connections between data objects
35964 */
35965 displayConnections : function() {
35966 return;
35967 if ( typeof this.connection != 'undefined') {
35968 this.objectLayer.removeFeatures(this.connections);
35969 this.connections = [];
35970 }
35971 if (this.options.connections) {
35972 var points = this.mds.getObjectsByZoom();
35973 for (var i in points ) {
35974 for (var j in points[i] ) {
35975
35976 }
35977 }
35978
35979 var slices = this.core.timeplot.getSlices();
35980 for (var i = 0; i < slices.length; i++) {
35981 for (var j = 0; j < slices[i].stacks.length; j++) {
35982 var e = slices[i].stacks[j].elements;
35983 if (e.length == 0) {
35984 continue;
35985 }
35986 var points = [];
35987 for (var k = 0; k < e.length; k++) {
35988 var point = this.mds.getCircle(j, e[k].index).feature.geometry;
35989 if (arrayIndex(points, point) == -1) {
35990 points.push(point);
35991 }
35992 }
35993 var matrix = new AdjMatrix(points.length);
35994 for (var k = 0; k < points.length - 1; k++) {
35995 for (var l = k + 1; l < points.length; l++) {
35996 matrix.setEdge(k, l, dist(points[k], points[l]));
35997 }
35998 }
35999 var tree = Prim(matrix);
36000 var lines = [];
36001 for (var z = 0; z < tree.length; z++) {
36002 lines.push(new OpenLayers.Geometry.LineString(new Array(points[tree[z].v1], points[tree[z].v2])));
36003 }
36004 this.connections[j].push({
36005 first : this.mds.getCircle(j, e[0].index).feature.geometry,
36006 last : this.mds.getCircle(j, e[e.length - 1].index).feature.geometry,
36007 lines : lines,
36008 time : slices[i].date
36009 });
36010 }
36011 }
36012 var ltm = this.core.timeplot.leftFlagTime;
36013 var rtm = this.core.timeplot.rightFlagTime;
36014 if (ltm == undefined || ltm == null) {
36015 return;
36016 } else {
36017 ltm = ltm.getTime();
36018 rtm = rtm.getTime();
36019 }
36020 // this.connectionLayer.destroyFeatures();
36021 if (thisConnections) {
36022 for (var i = 0; i < this.connections.length; i++) {
36023 var c = GeoTemConfig.colors[i];
36024 var style = {
36025 strokeColor : 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')',
36026 strokeOpacity : 0.5,
36027 strokeWidth : 3
36028 };
36029 var pointsToConnect = [];
36030 var last = undefined;
36031 for (var j = 0; j < this.connections[i].length; j++) {
36032 var c = this.connections[i][j];
36033 var ct = c.time.getTime();
36034 if (ct >= ltm && ct <= rtm) {
36035 if (last != undefined) {
36036 var line = new OpenLayers.Geometry.LineString(new Array(last, c.first));
36037 this.connectionLayer.addFeatures([new OpenLayers.Feature.Vector(line, null, style)]);
36038 }
36039 for (var k = 0; k < c.lines.length; k++) {
36040 this.connectionLayer.addFeatures([new OpenLayers.Feature.Vector(c.lines[k], null, style)]);
36041 }
36042 last = c.last;
36043 }
36044 }
36045 }
36046 // this.connectionLayer.redraw();
36047 }
36048 }
36049 },
36050
36051 /**
36052 * performs a zoom on the map
36053 * @param {int} delta the change of zoom levels
36054 */
36055 zoom : function(delta) {
36056 var zoom = this.getZoom() + delta;
36057 if (this.openlayersMap.baseLayer instanceof OpenLayers.Layer.WMS) {
36058 this.openlayersMap.zoomTo(zoom);
36059 } else {
36060 this.openlayersMap.zoomTo(Math.round(zoom));
36061 if (this.zoomSlider) {
36062 this.zoomSlider.setValue(this.getZoom());
36063 }
36064 }
36065 return true;
36066 },
36067
36068 deactivateCountrySelector : function() {
36069 this.openlayersMap.removeControl(this.selectCountry);
36070 this.selectCountry = undefined;
36071 },
36072
36073 activateCountrySelector : function(layer) {
36074 var map = this;
36075 if (this.options.countrySelect && this.options.mapSelectionTools) {
36076 this.selectCountry = new OpenLayers.Control.GetFeature({
36077 protocol : OpenLayers.Protocol.WFS.fromWMSLayer(layer),
36078 click : true
36079 });
36080 this.selectCountry.events.register("featureselected", this, function(e) {
36081 map.snapper();
36082 map.drawnPolygonHandler(e.feature.geometry);
36083 });
36084 this.openlayersMap.addControl(this.selectCountry);
36085 this.countrySelectionControl.enable();
36086 }
36087 },
36088
36089 setMap : function(index) {
36090 this.baselayerIndex = index;
36091 if (this.selectCountry) {
36092 // if( this.wmsOverlays.length == 0 ){
36093 this.deactivateCountrySelector();
36094 // }
36095 }
36096 if (this.baseLayers[index] instanceof OpenLayers.Layer.WMS) {
36097 // if( this.wmsOverlays.length == 0 ){
36098 this.activateCountrySelector(this.baseLayers[index]);
36099 // }
36100 } else {
36101 if (this.countrySelectionControl) {
36102 this.countrySelectionControl.disable();
36103 }
36104 }
36105 this.openlayersMap.zoomTo(Math.floor(this.getZoom()));
36106 this.openlayersMap.setBaseLayer(this.baseLayers[index]);
36107 if (this.baseLayers[index].name == 'Open Street Map') {
36108 this.gui.osmLink.style.visibility = 'visible';
36109 } else {
36110 this.gui.osmLink.style.visibility = 'hidden';
36111 }
36112 if (this.baseLayers[index].name == 'Open Street Map (MapQuest)') {
36113 this.gui.osmMapQuestLink.style.visibility = 'visible';
36114 } else {
36115 this.gui.osmMapQuestLink.style.visibility = 'hidden';
36116 }
36117 this.triggerMapChanged(this.baseLayers[index].name);
36118 },
36119
36120 //vhz added title to buttons
36121 initSelectorTools : function() {
36122 var map = this;
36123 this.mapControls = [];
36124
36125 if (this.options.squareSelect) {
36126 var button = document.createElement("div");
36127 $(button).addClass('mapControl');
36128 var activate = function() {
36129 map.drawSquare.activate();
36130 }
36131 var deactivate = function() {
36132 map.drawSquare.deactivate();
36133 }
36134 this.mapControls.push(new MapControl(this, button, 'square', activate, deactivate));
36135 }
36136 if (this.options.circleSelect) {
36137 var button = document.createElement("div");
36138 $(button).addClass('mapControl');
36139 var activate = function() {
36140 map.drawCircle.activate();
36141 }
36142 var deactivate = function() {
36143 map.drawCircle.deactivate();
36144 }
36145 this.mapControls.push(new MapControl(this, button, 'circle', activate, deactivate));
36146 }
36147 if (this.options.polygonSelect) {
36148 var button = document.createElement("div");
36149 $(button).addClass('mapControl');
36150 var activate = function() {
36151 map.drawPolygon.activate();
36152 }
36153 var deactivate = function() {
36154 map.drawPolygon.deactivate();
36155 }
36156 this.mapControls.push(new MapControl(this, button, 'polygon', activate, deactivate));
36157 }
36158 if (this.options.countrySelect) {
36159 var button = document.createElement("div");
36160 $(button).addClass('mapControl');
36161 var activate = function() {
36162 map.selectCountry.activate();
36163 map.dragControl.disable();
36164 }
36165 var deactivate = function() {
36166 map.selectCountry.deactivate();
36167 map.dragControl.enable();
36168 }
36169 this.countrySelectionControl = new MapControl(this, button, 'country', activate, deactivate);
36170 this.mapControls.push(this.countrySelectionControl);
36171 /*
36172 if( !(this.openlayersMap.baseLayer instanceof OpenLayers.Layer.WMS) ){
36173 this.countrySelectionControl.disable();
36174 }
36175 */
36176 }
36177 return this.mapControls;
36178 },
36179
36180 getZoom : function() {
36181 //calculate zoom from active resolution
36182 var resolution = this.openlayersMap.getResolution();
36183 var zoom = this.resolutions.indexOf(resolution);
36184 if (zoom == -1){
36185 //fractional zoom
36186 for (zoom = 0; zoom < this.resolutions.length; zoom++){
36187 if (resolution>=this.resolutions[zoom]){
36188 break;
36189 }
36190 }
36191 if (zoom == this.resolutions.length){
36192 zoom--;
36193 }
36194 }
36195 return(zoom);
36196 },
36197
36198 setMarker : function(lon, lat) {
36199 var p = new OpenLayers.Geometry.Point(lon, lat, null);
36200 p.transform(this.openlayersMap.displayProjection, this.openlayersMap.projection);
36201 this.openlayersMap.setCenter(new OpenLayers.LonLat(p.x, p.y));
36202 var size = new OpenLayers.Size(22, 33);
36203 var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
36204 var icon = new OpenLayers.Icon(GeoTemConfig.path + 'marker.png', size, offset);
36205 var marker = new OpenLayers.Marker(new OpenLayers.LonLat(p.x, p.y), icon);
36206 marker.setOpacity(0.9);
36207 this.markerLayer.setZIndex(parseInt(this.objectLayer.getZIndex()) + 1);
36208 this.markerLayer.addMarker(marker);
36209 // find nearest neighbor
36210 var nearestNeighbor;
36211 var points = this.mds.getAllObjects();
36212 if (points == null) {
36213 return;
36214 }
36215 var dist = function(p1, p2) {
36216 return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
36217 }
36218 var zoomLevels = this.openlayersMap.getNumZoomLevels();
36219 var pointSet = points[zoomLevels - 1];
36220 var closestDistance = undefined;
36221 var closestPoint;
36222 for (var i = 0; i < pointSet.length; i++) {
36223 for (var j = 0; j < pointSet[i].length; j++) {
36224 var point = pointSet[i][j].feature.geometry;
36225 var d = dist(point, p);
36226 if (!closestDistance || d < closestDistance) {
36227 closestDistance = d;
36228 closestPoint = point;
36229 }
36230 }
36231 }
36232 // find minimal zoom level
36233 var gap = 0;
36234 var x_s = this.gui.mapWindow.offsetWidth / 2 - gap;
36235 var y_s = this.gui.mapWindow.offsetHeight / 2 - gap;
36236 if (typeof closestPoint !== "undefined"){
36237 var xDist = Math.abs(p.x - closestPoint.x);
36238 var yDist = Math.abs(p.y - closestPoint.y);
36239 for (var i = 0; i < zoomLevels; i++) {
36240 var resolution = this.openlayersMap.getResolutionForZoom(zoomLevels - i - 1);
36241 if (xDist / resolution < x_s && yDist / resolution < y_s) {
36242 this.openlayersMap.zoomTo(zoomLevels - i - 1);
36243 if (this.zoomSlider) {
36244 this.zoomSlider.setValue(this.getZoom());
36245 }
36246 this.drawObjectLayer(false);
36247 break;
36248 }
36249 }
36250 } else {
36251 //if there are no points on the map, zoom to max
36252 this.openlayersMap.zoomTo(0);
36253 if (this.zoomSlider) {
36254 this.zoomSlider.setValue(this.getZoom());
36255 }
36256 this.drawObjectLayer(false);
36257 }
36258 },
36259
36260 removeMarker : function() {
36261 this.markerLayer.removeMarker(this.markerLayer.markers[0]);
36262 },
36263
36264 getLevelOfDetail : function() {
36265 var zoom = Math.floor(this.getZoom());
36266 if (zoom <= 1) {
36267 return 0;
36268 } else if (zoom <= 3) {
36269 return 1;
36270 } else if (zoom <= 8) {
36271 return 2;
36272 } else {
36273 return 3;
36274 }
36275 }
36276 }
36277 /*
36278 * TimeConfig.js
36279 *
36280 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
36281 *
36282 * This library is free software; you can redistribute it and/or
36283 * modify it under the terms of the GNU Lesser General Public
36284 * License as published by the Free Software Foundation; either
36285 * version 3 of the License, or (at your option) any later version.
36286 *
36287 * This library is distributed in the hope that it will be useful,
36288 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36289 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36290 * Lesser General Public License for more details.
36291 *
36292 * You should have received a copy of the GNU Lesser General Public
36293 * License along with this library; if not, write to the Free Software
36294 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
36295 * MA 02110-1301 USA
36296 */
36297
36298 /**
36299 * @class TimeConfig
36300 * Time Configuration File
36301 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
36302 * @release 1.0
36303 * @release date: 2012-07-27
36304 * @version date: 2012-07-27
36305 */
36306 function TimeConfig(options) {
36307
36308 this.options = {
36309 timeTitle : 'GeoTemCo Time View', // title will be shown in timeplot header
36310 timeIndex : 0, // index = position in date array; for multiple dates the 2nd timeplot refers to index 1
36311 timeWidth : false, // false or desired width css definition for the timeplot
36312 timeHeight : '100px', // false or desired height css definition for the timeplot
36313 defaultMinDate : new Date(2012, 0, 1), // required, when empty timelines are possible
36314 defaultMaxDate : new Date(), // required, when empty timelines are possible
36315 timeCanvasFrom : '#EEE', // time widget background gradient color top
36316 timeCanvasTo : '#EEE', // time widget background gradient color bottom
36317 rangeBoxColor : "white", // fill color for time range box
36318 rangeBorder : "1px solid #de7708", // border of frames
36319 dataInformation : true, // show/hide data information
36320 rangeAnimation : true, // show/hide animation buttons
36321 scaleSelection : true, // show/hide scale selection buttons
36322 linearScale : true, // true for linear value scaling, false for logarithmic
36323 unitSelection : true, // show/hide time unit selection dropdown
36324 timeUnit : -1, // minimum temporal unit (SimileAjax.DateTime or -1 if none) of the data
36325 timeMerge : false // if the elements of distinct datasets should be merged into one set or not
36326 };
36327 if ( typeof options != 'undefined') {
36328 $.extend(this.options, options);
36329 }
36330
36331 };
36332 /*
36333 * TimeGui.js
36334 *
36335 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
36336 *
36337 * This library is free software; you can redistribute it and/or
36338 * modify it under the terms of the GNU Lesser General Public
36339 * License as published by the Free Software Foundation; either
36340 * version 3 of the License, or (at your option) any later version.
36341 *
36342 * This library is distributed in the hope that it will be useful,
36343 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36344 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36345 * Lesser General Public License for more details.
36346 *
36347 * You should have received a copy of the GNU Lesser General Public
36348 * License along with this library; if not, write to the Free Software
36349 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
36350 * MA 02110-1301 USA
36351 */
36352
36353 /**
36354 * @class TimeGui
36355 * Time GUI Implementation
36356 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
36357 * @release 1.0
36358 * @release date: 2012-07-27
36359 * @version date: 2012-07-27
36360 *
36361 * @param {TimeWidget} parent time widget object
36362 * @param {HTML object} div parent div to append the time gui
36363 * @param {JSON} options time configuration
36364 */
36365 function TimeGui(plot, div, options, iid) {
36366
36367 var gui = this;
36368
36369 this.plot = plot;
36370
36371 this.container = div;
36372 if (options.timeWidth) {
36373 this.container.style.width = options.timeWidth;
36374 }
36375 if (options.timeHeight) {
36376 this.container.style.height = options.timeHeight;
36377 }
36378 this.container.style.position = 'relative';
36379
36380 var w = this.container.offsetWidth;
36381 var h = this.container.offsetHeight;
36382
36383 var toolbarTable = document.createElement("table");
36384 toolbarTable.setAttribute('class', 'ddbToolbar');
36385 this.container.appendChild(toolbarTable);
36386
36387 this.plotWindow = document.createElement("div");
36388 this.plotWindow.id = "plotWindow"+iid;
36389 this.plotWindow.setAttribute('class', 'plotWindow');
36390 // this.plotWindow.style.width = w + "px";
36391
36392 this.plotWindow.style.height = (h + 12) + "px";
36393 this.container.style.height = (h + 12) + "px";
36394
36395 this.plotWindow.onmousedown = function() {
36396 return false;
36397 }
36398
36399 this.plotContainer = document.createElement("div");
36400 this.plotContainer.id = "plotContainer"+iid;
36401 this.plotContainer.setAttribute('class', 'plotContainer');
36402 // this.plotContainer.style.width = w + "px";
36403 this.plotContainer.style.height = h + "px";
36404 this.plotContainer.style.position = "absolute";
36405 this.plotContainer.style.zIndex = 0;
36406 this.plotContainer.style.top = "12px";
36407 this.plotWindow.appendChild(this.plotContainer);
36408 this.container.appendChild(this.plotWindow);
36409
36410 this.timeplotDiv = document.createElement("div");
36411 this.timeplotDiv.style.left = "16px";
36412 this.timeplotDiv.style.width = (w - 32) + "px";
36413 this.timeplotDiv.style.height = h + "px";
36414 this.plotContainer.appendChild(this.timeplotDiv);
36415
36416 var cv = document.createElement("canvas");
36417 cv.setAttribute('class', 'plotCanvas');
36418 this.plotWindow.appendChild(cv);
36419 if (!cv.getContext && G_vmlCanvasManager)
36420 cv = G_vmlCanvasManager.initElement(cv);
36421 var ctx = cv.getContext('2d');
36422
36423 var setCanvas = function(){
36424 cv.width = gui.plotWindow.clientWidth;
36425 cv.height = gui.plotWindow.clientHeight;
36426 var gradient = ctx.createLinearGradient(0, 0, 0, gui.plotWindow.clientHeight);
36427 gradient.addColorStop(0, options.timeCanvasFrom);
36428 gradient.addColorStop(1, options.timeCanvasTo);
36429 ctx.fillStyle = gradient;
36430 ctx.fillRect(0, 0, gui.plotWindow.clientWidth, gui.plotWindow.clientHeight);
36431 }
36432 setCanvas();
36433
36434 this.resize = function(){
36435 gui.timeplotDiv.style.width = (gui.container.offsetWidth - 32) + "px";
36436 ctx.clearRect(0,0,gui.plotWindow.clientWidth, gui.plotWindow.clientHeight);
36437 if( typeof plot.datasets != "undefined" ){
36438 plot.redrawPlot();
36439 plot.resetOpacityPlots();
36440 }
36441 setCanvas();
36442 };
36443
36444 var titles = document.createElement("tr");
36445 toolbarTable.appendChild(titles);
36446 var tools = document.createElement("tr");
36447 toolbarTable.appendChild(tools);
36448
36449 this.timeUnitTitle = document.createElement("td");
36450 this.timeUnitTitle.innerHTML = GeoTemConfig.getString('timeUnit');
36451 this.timeUnitSelector = document.createElement("td");
36452 if (options.unitSelection) {
36453 tools.appendChild(this.timeUnitSelector);
36454 titles.appendChild(this.timeUnitTitle);
36455 }
36456
36457 this.timeAnimation = document.createElement("td");
36458 this.timeAnimation.innerHTML = GeoTemConfig.getString('timeAnimation');
36459 var timeAnimationTools = document.createElement("td");
36460
36461 var status;
36462 this.updateAnimationButtons = function(s) {
36463 status = s;
36464 if (status == 0) {
36465 gui.playButton.setAttribute('class', 'smallButton playDisabled');
36466 gui.pauseButton.setAttribute('class', 'smallButton pauseDisabled');
36467 } else if (status == 1) {
36468 gui.playButton.setAttribute('class', 'smallButton playEnabled');
36469 gui.pauseButton.setAttribute('class', 'smallButton pauseDisabled');
36470 } else {
36471 gui.playButton.setAttribute('class', 'smallButton playDisabled');
36472 gui.pauseButton.setAttribute('class', 'smallButton pauseEnabled');
36473 }
36474 };
36475 this.playButton = document.createElement("div");
36476 this.playButton.title = GeoTemConfig.getString('playButton');
36477 timeAnimationTools.appendChild(this.playButton);
36478 this.playButton.onclick = function() {
36479 if (status == 1) {
36480 plot.play();
36481 }
36482 }
36483
36484 this.pauseButton = document.createElement("div");
36485 this.pauseButton.title = GeoTemConfig.getString('pauseButton');
36486 timeAnimationTools.appendChild(this.pauseButton);
36487 this.pauseButton.onclick = function() {
36488 if (status == 2) {
36489 plot.stop();
36490 }
36491 }
36492
36493 this.valueScale = document.createElement("td");
36494 this.valueScale.innerHTML = GeoTemConfig.getString('valueScale');
36495 var valueScaleTools = document.createElement("td");
36496
36497 var linearPlot;
36498 var setValueScale = function(linScale) {
36499 if (linearPlot != linScale) {
36500 linearPlot = linScale;
36501 if (linearPlot) {
36502 gui.linButton.setAttribute('class', 'smallButton linearPlotActivated');
36503 gui.logButton.setAttribute('class', 'smallButton logarithmicPlotDeactivated');
36504 plot.drawLinearPlot();
36505 } else {
36506 gui.linButton.setAttribute('class', 'smallButton linearPlotDeactivated');
36507 gui.logButton.setAttribute('class', 'smallButton logarithmicPlotActivated');
36508 plot.drawLogarithmicPlot();
36509 }
36510 }
36511 };
36512 this.linButton = document.createElement("div");
36513 this.linButton.title = GeoTemConfig.getString('linearPlot');
36514 valueScaleTools.appendChild(this.linButton);
36515 this.linButton.onclick = function() {
36516 setValueScale(true);
36517 }
36518
36519 this.logButton = document.createElement("div");
36520 this.logButton.title = GeoTemConfig.getString('logarithmicPlot');
36521 valueScaleTools.appendChild(this.logButton);
36522 this.logButton.onclick = function() {
36523 setValueScale(false);
36524 }
36525 if (options.rangeAnimation) {
36526 titles.appendChild(this.timeAnimation);
36527 tools.appendChild(timeAnimationTools);
36528 this.updateAnimationButtons(0);
36529 }
36530
36531 if (options.scaleSelection) {
36532 titles.appendChild(this.valueScale);
36533 tools.appendChild(valueScaleTools);
36534 setValueScale(options.linearScale);
36535 }
36536
36537 if (GeoTemConfig.allowFilter) {
36538 this.filterTitle = document.createElement("td");
36539 titles.appendChild(this.filterTitle);
36540 this.filterTitle.innerHTML = GeoTemConfig.getString('filter');
36541 this.filterOptions = document.createElement("td");
36542 tools.appendChild(this.filterOptions);
36543 }
36544
36545 if (options.dataInformation) {
36546 this.infoTitle = document.createElement("td");
36547 this.infoTitle.innerHTML = options.timeTitle;
36548 titles.appendChild(this.infoTitle);
36549 var timeSum = document.createElement("td");
36550 this.timeElements = document.createElement("div");
36551 this.timeElements.setAttribute('class', 'ddbElementsCount');
36552 timeSum.appendChild(this.timeElements);
36553 tools.appendChild(timeSum);
36554 }
36555
36556 /*
36557 var tooltip = document.createElement("div");
36558 tooltip.setAttribute('class','ddbTooltip');
36559 toolbarTable.appendChild(tooltip);
36560
36561 tooltip.onmouseover = function(){
36562 /*
36563 getPublisher().Publish('TooltipContent', {
36564 content: GeoTemConfig.getString(GeoTemConfig.language,'timeHelp'),
36565 target: $(tooltip)
36566 });
36567
36568 }
36569 tooltip.onmouseout = function(){
36570 //getPublisher().Publish('TooltipContent');
36571 }
36572 */
36573
36574 this.setHeight = function() {
36575 this.container.style.height = (this.plotWindow.offsetHeight + toolbarTable.offsetHeight) + "px";
36576 };
36577
36578 this.updateTimeQuantity = function(count) {
36579 if (options.dataInformation) {
36580 this.plotCount = count;
36581 if (count != 1) {
36582 this.timeElements.innerHTML = this.beautifyCount(count) + " " + GeoTemConfig.getString('results');
36583 } else {
36584 this.timeElements.innerHTML = this.beautifyCount(count) + " " + GeoTemConfig.getString('result');
36585 }
36586 }
36587 }
36588
36589 this.setTimeUnitDropdown = function(units) {
36590 $(this.timeUnitSelector).empty();
36591 var gui = this;
36592 var timeUnits = [];
36593 var addUnit = function(unit, index) {
36594 var setUnit = function() {
36595 gui.plot.setTimeUnit(unit.unit);
36596 }
36597 timeUnits.push({
36598 name : unit.label,
36599 onclick : setUnit
36600 });
36601 }
36602 for (var i = 0; i < units.length; i++) {
36603 addUnit(units[i], i);
36604 }
36605 this.timeUnitDropdown = new Dropdown(this.timeUnitSelector, timeUnits, GeoTemConfig.getString('selectTimeUnit'), '100px');
36606 this.timeUnitDropdown.setEntry(0);
36607 }
36608 this.setTimeUnitDropdown([{
36609 name : 'none',
36610 id : -1
36611 }]);
36612
36613 this.beautifyCount = function(count) {
36614 var c = count + '';
36615 var p = 0;
36616 var l = c.length;
36617 while (l - p > 3) {
36618 p += 3;
36619 c = c.substring(0, l - p) + "." + c.substring(l - p);
36620 p++;
36621 l++;
36622 }
36623 return c;
36624 }
36625
36626 this.hideTimeUnitSelection = function() {
36627 this.timeUnitTitle.style.display = 'none';
36628 this.timeUnitSelector.style.display = 'none';
36629 }
36630 };
36631 /*
36632 * TimeWidget.js
36633 *
36634 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
36635 *
36636 * This library is free software; you can redistribute it and/or
36637 * modify it under the terms of the GNU Lesser General Public
36638 * License as published by the Free Software Foundation; either
36639 * version 3 of the License, or (at your option) any later version.
36640 *
36641 * This library is distributed in the hope that it will be useful,
36642 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36643 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36644 * Lesser General Public License for more details.
36645 *
36646 * You should have received a copy of the GNU Lesser General Public
36647 * License along with this library; if not, write to the Free Software
36648 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
36649 * MA 02110-1301 USA
36650 */
36651
36652 /**
36653 * @class TimeWidget
36654 * TableWidget Implementation
36655 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
36656 * @release 1.0
36657 * @release date: 2012-07-27
36658 * @version date: 2012-07-27
36659 *
36660 * @param {TimeWrapper} core wrapper for interaction to other widgets
36661 * @param {HTML object} div parent div to append the time widget div
36662 * @param {JSON} options user specified configuration that overwrites options in TimeConfig.js
36663 */
36664 TimeWidget = function(core, div, options) {
36665
36666 this.core = core;
36667 this.core.setWidget(this);
36668 this.timeplot
36669 this.dataSources
36670 this.eventSources
36671 this.tds
36672 this.timeGeometry
36673 this.valueGeometry
36674 this.canvas
36675
36676 this.leftFlagPole
36677 this.rightFlagPole
36678 this.rangeBox
36679 this.leftHandle
36680 this.rightHandle
36681
36682 this.leftFlagPos = null;
36683 this.leftFlagTime = null;
36684 this.rightFlagPos = null;
36685 this.rightFlagTime = null;
36686
36687 this.mouseDownTime
36688 this.mouseUpTime
36689 this.mouseTempTime
36690 this.mouseDownPos
36691 this.mouseUpPos
36692 this.mouseTempPos
36693
36694 this.status
36695 this.slider
36696
36697 this.iid = GeoTemConfig.getIndependentId('time');
36698 this.options = (new TimeConfig(options)).options;
36699 this.gui = new TimeGui(this, div, this.options, this.iid);
36700 this.initialize();
36701
36702 }
36703
36704 TimeWidget.prototype = {
36705
36706 /**
36707 * clears the timeplot canvas and the timeGeometry properties
36708 */
36709 clearTimeplot : function() {
36710 this.timeplot._clearCanvas();
36711 this.timeGeometry._earliestDate = null;
36712 this.timeGeometry._latestDate = null;
36713 this.valueGeometry._minValue = 0;
36714 this.valueGeometry._maxValue = 0;
36715 this.highlightedSlice = undefined;
36716 this.timeGeometry._clearLabels();
36717 this.selection = new Selection();
36718 },
36719
36720 /**
36721 * initializes the timeplot elements with arrays of time objects
36722 * @param {TimeObject[][]} timeObjects an array of time objects from different (1-4) sets
36723 */
36724 initWidget : function(datasets) {
36725 this.datasets = datasets;
36726 var timeObjects = [];
36727 for (var i = 0; i < datasets.length; i++) {
36728 timeObjects.push(datasets[i].objects);
36729 }
36730 this.clearTimeplot();
36731 this.reset();
36732 for (var i = 0; i < this.timeplot._plots.length; i++) {
36733 this.timeplot._plots[i].dispose();
36734 }
36735 this.dataSources = new Array();
36736 this.plotInfos = new Array();
36737 this.eventSources = new Array();
36738 var granularity = 0;
36739 this.count = 0;
36740 for (var i = 0; i < timeObjects.length; i++) {
36741 if( i==0 || !this.options.timeMerge ){
36742 var eventSource = new Timeplot.DefaultEventSource();
36743 var dataSource = new Timeplot.ColumnSource(eventSource, 1);
36744 this.dataSources.push(dataSource);
36745 this.eventSources.push(eventSource);
36746 var c = GeoTemConfig.getColor(i);
36747 var plotInfo = Timeplot.createPlotInfo({
36748 id : "plot" + i,
36749 dataSource : dataSource,
36750 timeGeometry : this.timeGeometry,
36751 valueGeometry : this.valueGeometry,
36752 fillGradient : false,
36753 lineColor : 'rgba(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ', 1)',
36754 fillColor : 'rgba(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ', 0.3)',
36755 showValues : true
36756 });
36757 this.plotInfos.push(plotInfo);
36758 }
36759 for (var j = 0; j < timeObjects[i].length; j++) {
36760 var o = timeObjects[i][j];
36761 if (o.isTemporal) {
36762 var g = o.dates[this.options.timeIndex].granularity;
36763 if (g == null) {
36764 continue;
36765 } else if (g > granularity) {
36766 granularity = g;
36767 }
36768 this.count += o.weight;
36769 }
36770 }
36771 }
36772 this.timeGeometry._granularity = granularity;
36773 this.timeGeometry._clearLabels();
36774 this.timeplot.resetPlots(this.plotInfos);
36775 if (this.plotInfos.length == 0) {
36776 this.initLabels(this.timeplot.regularGrid());
36777 return;
36778 }
36779 this.timeGeometry.extendedDataSource = this.tds;
36780 this.tds.initialize(this.dataSources, this.eventSources, timeObjects, granularity, this.options.timeUnit, this.gui.timeplotDiv.offsetWidth);
36781 this.gui.setTimeUnitDropdown(this.tds.availableUnits);
36782 this.gui.timeUnitDropdown.setEntry(this.tds.getUnitIndex());
36783 var plots = this.timeplot._plots;
36784 for (var i = 0; i < plots.length; i++) {
36785 plots[i].pins = [];
36786 plots[i].style = this.style;
36787 for (var j = 0; j < this.tds.getSliceNumber(); j++) {
36788 plots[i].pins.push({
36789 height : 0,
36790 count : 0
36791 });
36792 }
36793 }
36794 /*
36795 var levels = Math.round( (this.tds.timeSlices.length-3)/2 );
36796 if( GeoTemConfig.timeZoom ){
36797 this.zoomSlider.setMaxAndLevels(levels,levels);
36798 }
36799 */
36800 this.timeplot.repaint();
36801 this.timeplot._resizeCanvas();
36802 // set maximum number of slider steps
36803 var slices = this.tds.timeSlices.length;
36804 var numSlices = Math.floor(slices / this.canvas.width * this.canvas.height + 0.5);
36805
36806 this.initLabels([]);
36807 this.initOverview();
36808 this.gui.updateTimeQuantity(this.count);
36809
36810 },
36811
36812 setTimeUnit : function(unit) {
36813 this.clearTimeplot();
36814 this.reset();
36815 this.tds.setTimeUnit(unit);
36816 var plots = this.timeplot._plots;
36817 for (var i = 0; i < plots.length; i++) {
36818 plots[i].pins = [];
36819 plots[i].style = this.style;
36820 for (var j = 0; j < this.tds.getSliceNumber(); j++) {
36821 plots[i].pins.push({
36822 height : 0,
36823 count : 0
36824 });
36825 }
36826 }
36827 this.initLabels([]);
36828 },
36829
36830 /**
36831 * initializes the timeplot for the Spatio Temporal Interface.
36832 * all elements (including their events) that are needed for user interaction are instantiated here, the slider element as well
36833 */
36834 initialize : function() {
36835
36836 this.status = 0;
36837 this.selection = new Selection();
36838 this.paused = true;
36839 this.dataSources = new Array();
36840 this.plotInfos = new Array();
36841 this.eventSources = new Array();
36842 this.timeGeometry = new Timeplot.DefaultTimeGeometry({
36843 gridColor : "#000000",
36844 axisLabelsPlacement : "top"
36845 });
36846 this.style = 'graph';
36847 this.timeGeometry._hideLabels = true;
36848 this.timeGeometry._granularity = 0;
36849 this.valueGeometry = new Timeplot.LogarithmicValueGeometry({
36850 min : 0
36851 });
36852 this.valueGeometry.actLinear();
36853
36854 var plot = this;
36855
36856 this.timeplot = Timeplot.create(this.gui.timeplotDiv, this.plotInfos);
36857 this.tds = new TimeDataSource(this.options);
36858
36859 this.canvas = this.timeplot.getCanvas();
36860
36861 this.leftFlagPole = this.timeplot.putDiv("leftflagpole", "timeplot-dayflag-pole");
36862 this.rightFlagPole = this.timeplot.putDiv("rightflagpole", "timeplot-dayflag-pole");
36863 SimileAjax.Graphics.setOpacity(this.leftFlagPole, 50);
36864 SimileAjax.Graphics.setOpacity(this.rightFlagPole, 50);
36865
36866 this.rangeBox = this.timeplot.putDiv("rangebox", "range-box");
36867 this.rangeBox.style.backgroundColor = plot.options.rangeBoxColor;
36868 this.rangeBox.style.border = plot.options.rangeBorder;
36869
36870 this.leftHandle = document.createElement("div");
36871 this.rightHandle = document.createElement("div");
36872 this.gui.plotWindow.appendChild(this.leftHandle);
36873 this.gui.plotWindow.appendChild(this.rightHandle);
36874 this.leftHandle.title = GeoTemConfig.getString('leftHandle');
36875 this.rightHandle.title = GeoTemConfig.getString('rightHandle');
36876
36877 this.leftHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "leftHandle.png" + ")";
36878 this.leftHandle.setAttribute('class', 'plotHandle plotHandleIcon');
36879 this.rightHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "rightHandle.png" + ")";
36880 this.rightHandle.setAttribute('class', 'plotHandle plotHandleIcon');
36881
36882 this.poles = this.timeplot.putDiv("poles", "pole");
36883 this.timeplot.placeDiv(this.poles, {
36884 left : 0,
36885 bottom : 0,
36886 width : this.canvas.width,
36887 height : this.canvas.height,
36888 display : "block"
36889 });
36890 this.poles.appendChild(document.createElement("canvas"));
36891
36892 this.filterBar = new FilterBar(this, this.gui.filterOptions);
36893
36894 var plot = this;
36895
36896 this.dragButton = document.createElement("div");
36897 this.dragButton.title = GeoTemConfig.getString('dragTimeRange');
36898 this.cancelButton = document.createElement("div");
36899 this.cancelButton.title = GeoTemConfig.getString('clearSelection');
36900 this.cancelButton.onclick = function() {
36901 plot.deselection();
36902 }
36903
36904 this.toolbar = document.createElement("div");
36905 this.toolbar.setAttribute('class', 'plotToolbar');
36906 this.toolbar.style.borderTop = plot.options.rangeBorder;
36907 this.toolbar.style.textAlign = "center";
36908 this.gui.plotWindow.appendChild(this.toolbar);
36909
36910 this.toolbarAbsoluteDiv = document.createElement("div");
36911 this.toolbarAbsoluteDiv.setAttribute('class', 'absoluteToolbar');
36912 this.toolbar.appendChild(this.toolbarAbsoluteDiv);
36913
36914 this.dragButton.setAttribute('class', 'dragTimeRangeAlt');
36915 this.dragButton.style.backgroundImage = "url(" + GeoTemConfig.path + "drag.png" + ")";
36916 // this.zoomButton.setAttribute('class','zoomRangeAlt');
36917 this.cancelButton.setAttribute('class', 'cancelRangeAlt');
36918 this.toolbarAbsoluteDiv.appendChild(this.dragButton);
36919 this.toolbarAbsoluteDiv.style.width = this.dragButton.offsetWidth + "px";
36920 // this.gui.plotWindow.appendChild(this.zoomButton);
36921 this.gui.plotWindow.appendChild(this.cancelButton);
36922
36923 this.overview = document.createElement("div");
36924 this.overview.setAttribute('class', 'timeOverview');
36925 this.gui.plotWindow.appendChild(this.overview);
36926
36927 var mousedown = false;
36928 this.shift = function(shift) {
36929 if (!mousedown) {
36930 return;
36931 }
36932 if (plot.tds.setShift(shift)) {
36933 plot.redrawPlot();
36934 }
36935 setTimeout(function() {
36936 plot.shift(shift);
36937 }, 200);
36938 }
36939 var shiftPressed = function(shift) {
36940 mousedown = true;
36941 document.onmouseup = function() {
36942 mousedown = false;
36943 document.onmouseup = null;
36944 }
36945 plot.shift(shift);
36946 }
36947
36948 this.shiftLeft = document.createElement("div");
36949 this.shiftLeft.setAttribute('class', 'shiftLeft');
36950 this.gui.plotWindow.appendChild(this.shiftLeft);
36951 this.shiftLeft.onmousedown = function() {
36952 shiftPressed(1);
36953 }
36954
36955 this.shiftRight = document.createElement("div");
36956 this.shiftRight.setAttribute('class', 'shiftRight');
36957 this.gui.plotWindow.appendChild(this.shiftRight);
36958 this.shiftRight.onmousedown = function() {
36959 shiftPressed(-1);
36960 }
36961
36962 this.plotLabels = document.createElement("div");
36963 this.plotLabels.setAttribute('class', 'plotLabels');
36964 this.gui.plotWindow.appendChild(this.plotLabels);
36965
36966 this.initLabels(this.timeplot.regularGrid());
36967
36968 //Finds the time corresponding to the position x on the timeplot
36969 var getCorrelatedTime = function(x) {
36970 if (x >= plot.canvas.width)
36971 x = plot.canvas.width;
36972 if (isNaN(x) || x < 0)
36973 x = 0;
36974 var t = plot.timeGeometry.fromScreen(x);
36975 if (t == 0)
36976 return;
36977 return plot.dataSources[0].getClosestValidTime(t);
36978 }
36979 //Finds the position corresponding to the time t on the timeplot
36980 var getCorrelatedPosition = function(t) {
36981 var x = plot.timeGeometry.toScreen(t);
36982 if (x >= plot.canvas.width)
36983 x = plot.canvas.width;
36984 if (isNaN(x) || x < 0)
36985 x = 0;
36986 return x;
36987 }
36988 //Maps the 2 positions in the right order to left and right bound of the chosen timeRange
36989 var mapPositions = function(pos1, pos2) {
36990 if (pos1 > pos2) {
36991 plot.leftFlagPos = pos2;
36992 plot.rightFlagPos = pos1;
36993 } else {
36994 plot.leftFlagPos = pos1;
36995 plot.rightFlagPos = pos2;
36996 }
36997 plot.leftFlagTime = plot.dataSources[0].getClosestValidTime(plot.timeGeometry.fromScreen(plot.leftFlagPos));
36998 plot.rightFlagTime = plot.dataSources[0].getClosestValidTime(plot.timeGeometry.fromScreen(plot.rightFlagPos));
36999 }
37000 //Sets the divs corresponding to the actual chosen timeRange
37001 var setRangeDivs = function() {
37002 plot.leftFlagPole.style.visibility = "visible";
37003 plot.rightFlagPole.style.visibility = "visible";
37004 plot.rangeBox.style.visibility = "visible";
37005 plot.timeplot.placeDiv(plot.leftFlagPole, {
37006 left : plot.leftFlagPos,
37007 bottom : 0,
37008 height : plot.canvas.height,
37009 display : "block"
37010 });
37011 plot.timeplot.placeDiv(plot.rightFlagPole, {
37012 left : plot.rightFlagPos,
37013 bottom : 0,
37014 height : plot.canvas.height,
37015 display : "block"
37016 });
37017 var boxWidth = plot.rightFlagPos - plot.leftFlagPos;
37018 if (plot.popup) {
37019 plot.popupClickDiv.style.visibility = "visible";
37020 plot.timeplot.placeDiv(plot.popupClickDiv, {
37021 left : plot.leftFlagPos,
37022 width : boxWidth + 1,
37023 height : plot.canvas.height,
37024 display : "block"
37025 });
37026 }
37027 plot.timeplot.placeDiv(plot.rangeBox, {
37028 left : plot.leftFlagPos,
37029 width : boxWidth + 1,
37030 height : plot.canvas.height,
37031 display : "block"
37032 });
37033 var plots = plot.timeplot._plots;
37034 for ( i = 0; i < plots.length; i++) {
37035 plots[i].fullOpacityPlot(plot.leftFlagTime, plot.rightFlagTime, plot.leftFlagPos, plot.rightFlagPos, GeoTemConfig.getColor(i));
37036 plots[i].opacityPlot.style.visibility = "visible";
37037 }
37038 var unit = plot.tds.unit;
37039
37040 var top = plot.gui.plotContainer.offsetTop;
37041 var left = plot.gui.plotContainer.offsetLeft;
37042 var leftPos = plot.leftFlagPole.offsetLeft + plot.timeplot.getElement().offsetLeft;
37043 var rightPos = plot.rightFlagPole.offsetLeft + plot.timeplot.getElement().offsetLeft;
37044 var rW = rightPos - leftPos;
37045 var pW = plot.canvas.width;
37046 var pL = plot.timeplot.getElement().offsetLeft;
37047
37048 var handleTop = top + Math.floor(plot.gui.timeplotDiv.offsetHeight / 2 - plot.leftHandle.offsetHeight / 2);
37049 plot.leftHandle.style.visibility = "visible";
37050 plot.rightHandle.style.visibility = "visible";
37051 plot.leftHandle.style.left = (leftPos - plot.leftHandle.offsetWidth / 2) + "px";
37052 plot.rightHandle.style.left = (rightPos - plot.rightHandle.offsetWidth + 1 + plot.rightHandle.offsetWidth / 2) + "px";
37053 plot.leftHandle.style.top = handleTop + "px";
37054 plot.rightHandle.style.top = handleTop + "px";
37055 if (rightPos == leftPos) {
37056 plot.rightHandle.style.visibility = "hidden";
37057 plot.leftHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "mergedHandle.png" + ")";
37058 } else {
37059 plot.leftHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "leftHandle.png" + ")";
37060 }
37061 plot.cancelButton.style.visibility = "visible";
37062 plot.cancelButton.style.top = top + "px";
37063
37064 if (rW > plot.cancelButton.offsetWidth) {
37065 plot.cancelButton.style.left = (left + rightPos - plot.cancelButton.offsetWidth) + "px";
37066 } else {
37067 plot.cancelButton.style.left = (left + rightPos) + "px";
37068 }
37069 var tW = plot.toolbarAbsoluteDiv.offsetWidth;
37070 if (rW >= tW) {
37071 plot.toolbar.style.left = leftPos + "px";
37072 plot.toolbar.style.width = (rW + 1) + "px";
37073 plot.toolbarAbsoluteDiv.style.left = ((rW - tW) / 2) + "px";
37074 } else {
37075 plot.toolbar.style.left = (pL + plot.leftFlagPos * (pW - tW) / (pW - rW)) + "px";
37076 plot.toolbar.style.width = (tW + 2) + "px";
37077 plot.toolbarAbsoluteDiv.style.left = "0px";
37078 }
37079 plot.toolbar.style.top = (top + plot.timeplot.getElement().offsetHeight) + "px";
37080 plot.toolbar.style.visibility = "visible";
37081 plot.toolbarAbsoluteDiv.style.visibility = "visible";
37082
37083 }
37084 var getAbsoluteLeft = function(div) {
37085 var left = 0;
37086 while (div) {
37087 left += div.offsetLeft;
37088 div = div.offsetParent;
37089 }
37090 return left;
37091 }
37092 var timeplotLeft = getAbsoluteLeft(plot.timeplot.getElement());
37093
37094 var checkPolesForStyle = function(x) {
37095 if (plot.style == 'bars' && plot.leftFlagTime == plot.rightFlagTime) {
37096 var index = plot.tds.getSliceIndex(plot.leftFlagTime);
37097 var time1 = plot.leftFlagTime;
37098 var pos1 = plot.leftFlagPos;
37099 var time2, pos2;
37100 if (index == 0) {
37101 time2 = plot.tds.getSliceTime(index + 1);
37102 } else if (index == plot.tds.getSliceNumber() - 1) {
37103 time2 = plot.tds.getSliceTime(index - 1);
37104 } else {
37105 if (x < plot.leftFlagPos) {
37106 time2 = plot.tds.getSliceTime(index - 1);
37107 } else {
37108 time2 = plot.tds.getSliceTime(index + 1);
37109 }
37110 }
37111 pos2 = plot.timeGeometry.toScreen(time2);
37112 mapPositions(pos1, pos2, time1, time2);
37113 }
37114 }
37115 var startX, startY, multiplier;
37116
37117 // mousemove function that causes moving selection of objects and toolbar divs
37118 var moveToolbar = function(start, actual) {
37119 var pixelShift = actual - start;
37120 if (plot.status == 2) {
37121 var newTime = getCorrelatedTime(startX + pixelShift);
37122 if (newTime == plot.mouseTempTime) {
37123 return;
37124 }
37125 plot.mouseTempTime = newTime;
37126 plot.mouseTempPos = plot.timeGeometry.toScreen(plot.mouseTempTime);
37127 mapPositions(plot.mouseDownPos, plot.mouseTempPos);
37128 } else if (plot.status == 3) {
37129 pixelShift *= multiplier;
37130 var plotPos = actual - timeplotLeft;
37131 if (plotPos <= plot.canvas.width / 2) {
37132 var newTime = getCorrelatedTime(startX + pixelShift);
37133 if (newTime == plot.leftFlagTime) {
37134 return;
37135 }
37136 plot.leftFlagTime = newTime;
37137 var diff = plot.leftFlagPos;
37138 plot.leftFlagPos = plot.timeGeometry.toScreen(plot.leftFlagTime);
37139 diff -= plot.leftFlagPos;
37140 plot.rightFlagTime = getCorrelatedTime(plot.rightFlagPos - diff);
37141 plot.rightFlagPos = plot.timeGeometry.toScreen(plot.rightFlagTime);
37142 } else {
37143 var newTime = getCorrelatedTime(startY + pixelShift);
37144 if (newTime == plot.rightFlagTime) {
37145 return;
37146 }
37147 plot.rightFlagTime = newTime;
37148 var diff = plot.rightFlagPos;
37149 plot.rightFlagPos = plot.timeGeometry.toScreen(plot.rightFlagTime);
37150 diff -= plot.rightFlagPos;
37151 plot.leftFlagTime = getCorrelatedTime(plot.leftFlagPos - diff);
37152 plot.leftFlagPos = plot.timeGeometry.toScreen(plot.leftFlagTime);
37153 }
37154 }
37155 checkPolesForStyle(actual - timeplotLeft);
37156 setRangeDivs();
37157 plot.timeSelection();
37158 }
37159 // fakes user interaction mouse move
37160 var playIt = function(start, actual, reset) {
37161 if (!plot.paused) {
37162 var pixel = plot.canvas.width / (plot.tds.timeSlices.length - 1 ) / 5;
37163 var wait = 20 * pixel;
37164 if (reset) {
37165 actual = 0;
37166 }
37167 moveToolbar(start, actual);
37168 if (plot.rightFlagPos >= plot.canvas.width) {
37169 reset = true;
37170 wait = 1000;
37171 } else {
37172 reset = false;
37173 }
37174 setTimeout(function() {
37175 playIt(start, actual + pixel, reset)
37176 }, wait);
37177 }
37178 }
37179 var setMultiplier = function() {
37180 var rangeWidth = plot.rightFlagPos - plot.leftFlagPos;
37181 var toolbarWidth = plot.toolbarAbsoluteDiv.offsetWidth;
37182 var plotWidth = plot.canvas.width;
37183 if (rangeWidth < toolbarWidth) {
37184 multiplier = (plotWidth - rangeWidth) / (plotWidth - toolbarWidth);
37185 } else {
37186 multiplier = 1;
37187 }
37188 }
37189 /**
37190 * starts the animation
37191 */
37192 this.play = function() {
37193 if (this.leftFlagPos == null) {
37194 return;
37195 }
37196 plot.paused = false;
37197 plot.gui.updateAnimationButtons(2);
37198 plot.status = 3;
37199 setMultiplier();
37200 startX = plot.leftFlagPos;
37201 startY = plot.rightFlagPos;
37202 var position = Math.round(plot.leftFlagPos);
37203 playIt(position, position + 1, false);
37204 }
37205 /**
37206 * stops the animation
37207 */
37208 this.stop = function() {
37209 plot.paused = true;
37210 plot.status = 0;
37211 plot.gui.updateAnimationButtons(1);
37212 }
37213 // triggers the mousemove function to move the range and toolbar
37214 var toolbarEvent = function(evt) {
37215 var left = GeoTemConfig.getMousePosition(evt).left;
37216 document.onmousemove = function(evt) {
37217 moveToolbar(left, GeoTemConfig.getMousePosition(evt).left);
37218 if (plot.popup) {
37219 plot.popup.reset();
37220 }
37221 }
37222 }
37223 var initializeLeft = function() {
37224 plot.mouseDownTime = plot.rightFlagTime;
37225 plot.mouseTempTime = plot.leftFlagTime;
37226 plot.mouseDownPos = plot.timeGeometry.toScreen(plot.mouseDownTime);
37227 startX = plot.leftFlagPos;
37228 }
37229 var initializeRight = function() {
37230 plot.mouseDownTime = plot.leftFlagTime;
37231 plot.mouseTempTime = plot.rightFlagTime;
37232 plot.mouseDownPos = plot.timeGeometry.toScreen(plot.mouseDownTime);
37233 startX = plot.rightFlagPos;
37234 }
37235 var initializeDrag = function() {
37236 startX = plot.leftFlagPos;
37237 startY = plot.rightFlagPos;
37238 setMultiplier();
37239 }
37240 var checkBorders = function() {
37241 if (plot.style == 'bars' && plot.mouseUpTime == plot.mouseDownTime) {
37242 var index = plot.tds.getSliceIndex(plot.mouseUpTime);
37243 if (index == 0) {
37244 plot.mouseUpTime = plot.tds.getSliceTime(index + 1);
37245 } else if (index == plot.tds.getSliceNumber() - 1) {
37246 plot.mouseUpTime = plot.tds.getSliceTime(index - 1);
37247 } else {
37248 if (plot.x < plot.leftFlagPos) {
37249 plot.mouseUpTime = plot.tds.getSliceTime(index - 1);
37250 } else {
37251 plot.mouseUpTime = plot.tds.getSliceTime(index + 1);
37252 }
37253 }
37254 }
37255 }
37256 // handles mousedown on left handle
37257 this.leftHandle.onmousedown = function(evt) {
37258 if (plot.status != 2) {
37259
37260 initializeLeft();
37261 plot.status = 2;
37262 toolbarEvent(evt);
37263 document.onmouseup = function() {
37264 document.onmousemove = null;
37265 document.onmouseup = null;
37266 plot.stop();
37267 }
37268 }
37269 }
37270 // handles mousedown on right handle
37271 this.rightHandle.onmousedown = function(evt) {
37272 if (plot.status != 2) {
37273 initializeRight();
37274 plot.status = 2;
37275 toolbarEvent(evt);
37276 document.onmouseup = function() {
37277 document.onmousemove = null;
37278 document.onmouseup = null;
37279 plot.stop();
37280 }
37281 }
37282 }
37283 // handles mousedown on drag button
37284 this.dragButton.onmousedown = function(evt) {
37285 if (plot.status != 3) {
37286 plot.status = 3;
37287 initializeDrag();
37288 toolbarEvent(evt);
37289 document.onmouseup = function() {
37290 document.onmousemove = null;
37291 document.onmouseup = null;
37292 plot.stop();
37293 }
37294 }
37295 }
37296 // handles mousedown-Event on timeplot
37297 var mouseDownHandler = function(elmt, evt, target) {
37298 if (plot.dataSources.length > 0) {
37299
37300 plot.x = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).x);
37301 if (plot.status == 0) {
37302 var time = getCorrelatedTime(plot.x);
37303 if (plot.leftFlagPos != null && plot.popup && time >= plot.leftFlagTime && time <= plot.rightFlagTime) {
37304 var x = plot.leftFlagPos + (plot.rightFlagPos - plot.leftFlagPos) / 2;
37305 var elements = [];
37306 for (var i = 0; i < plot.dataSources.length; i++) {
37307 elements.push([]);
37308 }
37309 for (var i = 0; i < plot.selectedObjects.length; i++) {
37310 if (plot.selectedObjects[i].value == 1) {
37311 for (var j = 0; j < plot.selectedObjects[i].objects.length; j++) {
37312 elements[j] = elements[j].concat(plot.selectedObjects[i].objects[j]);
37313 }
37314 }
37315 }
37316 var labels = [];
37317 for (var i = 0; i < elements.length; i++) {
37318 if (elements[i].length == 0) {
37319 continue;
37320 }
37321 var c = GeoTemConfig.getColor(i);
37322 var color = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
37323 var div = document.createElement("div");
37324 div.setAttribute('class', 'tagCloudItem');
37325 div.style.color = color;
37326 var label = {
37327 div : div,
37328 elements : elements[i]
37329 };
37330 var weight = 0;
37331 for (j in elements[i] ) {
37332 weight += elements[i][j].weight;
37333 }
37334 var fs = 2 * weight / 1000;
37335 if (fs > 2) {
37336 fs = 2;
37337 }
37338 div.style.fontSize = (1 + fs) + "em";
37339 div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em " + c.hex;
37340 if (weight == 1) {
37341 div.innerHTML = weight + " object";
37342 } else {
37343 div.innerHTML = weight + " objects";
37344 }
37345 var appendMouseFunctions = function(label, div, color) {
37346 div.onclick = function() {
37347 plot.popup.showLabelContent(label);
37348 div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em " + color;
37349 }
37350 div.onmouseover = function() {
37351 div.style.textShadow = "0 -1px " + color + ", 1px 0 " + color + ", 0 1px " + color + ", -1px 0 " + color;
37352 }
37353 div.onmouseout = function() {
37354 div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em " + color;
37355 }
37356 }
37357 appendMouseFunctions(label, div, c.hex);
37358 labels.push(label);
37359 }
37360 if (labels.length > 0) {
37361 plot.popup.createPopup(x + 20, 0, labels);
37362 }
37363 } else {
37364 plot.deselection();
37365 plot.status = 1;
37366 plot.mouseDownTime = time;
37367 plot.mouseTempTime = plot.mouseDownTime;
37368 plot.mouseDownPos = plot.timeGeometry.toScreen(plot.mouseDownTime);
37369 mapPositions(plot.mouseDownPos, plot.mouseDownPos, plot.mouseDownTime, plot.mouseDownTime);
37370 // handles mouseup-Event on timeplot
37371 document.onmouseup = function() {
37372 if (plot.status == 1) {
37373 plot.mouseUpTime = plot.mouseTempTime;
37374 plot.mouseUpPos = plot.timeGeometry.toScreen(plot.mouseUpTime);
37375 mapPositions(plot.mouseDownPos, plot.mouseUpPos, plot.mouseDownTime, plot.mouseUpTime);
37376 checkPolesForStyle(plot.x);
37377 setRangeDivs();
37378 plot.timeSelection();
37379 plot.gui.updateAnimationButtons(1);
37380 document.onmouseup = null;
37381 plot.status = 0;
37382 }
37383 }
37384 }
37385 }
37386 }
37387 }
37388 // handles mousemove-Event on timeplot
37389 var mouseMoveHandler = function(elmt, evt, target) {
37390 if (plot.dataSources.length > 0) {
37391 plot.x = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).x);
37392 if (plot.status == 1) {
37393 plot.mouseTempTime = getCorrelatedTime(plot.x);
37394 plot.mouseTempPos = plot.timeGeometry.toScreen(plot.mouseTempTime);
37395 mapPositions(plot.mouseDownPos, plot.mouseTempPos, plot.mouseDownTime, plot.mouseTempTime);
37396 checkPolesForStyle(plot.x);
37397 setRangeDivs();
37398 }
37399 }
37400 }
37401 // handles mouseout-Event on timeplot
37402 var mouseOutHandler = function(elmt, evt, target) {
37403 if (plot.dataSources.length > 0) {
37404 var x = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).x);
37405 var y = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).y);
37406 if (x > plot.canvas.width - 2 || isNaN(x) || x < 2) {
37407 plot.timeHighlight(true);
37408 plot.highlightedSlice = undefined;
37409 } else if (y > plot.canvas.height - 2 || isNaN(y) || y < 2) {
37410 plot.timeHighlight(true);
37411 plot.highlightedSlice = undefined;
37412 }
37413 }
37414 }
37415 // handles mouse(h)over-Event on timeplot
37416 var mouseHoverHandler = function(elmt, evt, target) {
37417 if (plot.dataSources.length > 0) {
37418 var x = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).x);
37419 var time = getCorrelatedTime(x);
37420 if (time == undefined) {
37421 return;
37422 }
37423 var highlightSlice;
37424 var slices = plot.tds.timeSlices;
37425 var index = plot.tds.getSliceIndex(time);
37426 if (plot.style == 'graph') {
37427 highlightSlice = slices[index];
37428 }
37429 if (plot.style == 'bars') {
37430 var pos = plot.timeGeometry.toScreen(time);
37431 if (x < pos && index > 0) {
37432 highlightSlice = slices[index - 1];
37433 } else {
37434 highlightSlice = slices[index];
37435 }
37436 }
37437 if (plot.highlightedSlice == undefined || plot.highlightedSlice != highlightSlice) {
37438 plot.highlightedSlice = highlightSlice;
37439 plot.timeHighlight(false);
37440 }
37441 }
37442 }
37443
37444 this.redrawPlot = function() {
37445 plot.clearTimeplot();
37446 plot.tds.reset(this.timeGeometry);
37447 plot.timeplot._prepareCanvas();
37448 plot.timeplot.repaint();
37449 if (plot.leftFlagPos != null) {
37450 plot.leftFlagPos = getCorrelatedPosition(plot.leftFlagTime);
37451 plot.rightFlagPos = getCorrelatedPosition(plot.rightFlagTime);
37452 setRangeDivs();
37453 } else {
37454 plot.displayOverlay();
37455 }
37456 plot.initLabels([]);
37457 plot.updateOverview();
37458 }
37459
37460 this.resetOpacityPlots = function() {
37461 var plots = plot.timeplot._plots;
37462 for ( var i = 0; i < plots.length; i++) {
37463 plots[i]._opacityCanvas.width = this.canvas.width;
37464 plots[i]._opacityCanvas.height = this.canvas.height;
37465 if( plot.leftFlagTime != null ){
37466 plots[i].fullOpacityPlot(plot.leftFlagTime, plot.rightFlagTime, plot.leftFlagPos, plot.rightFlagPos, GeoTemConfig.getColor(i));
37467 }
37468 }
37469 }
37470
37471 /**
37472 * handles zoom of the timeplot
37473 * @param {int} delta the change of zoom
37474 * @param {Date} time a time that corresponds to a slice, that was clicked
37475 */
37476 /*
37477 this.zoom = function(delta,time){
37478 if( this.eventSources.length == 0 ){
37479 if( GeoTemConfig.timeZoom ){
37480 this.zoomSlider.setValue(0);
37481 }
37482 return false;
37483 }
37484 if( time == null ){
37485 time = getCorrelatedTime(this.canvas.width/2);
37486 }
37487 if( this.tds.setZoom(delta,time,this.leftFlagTime,this.rightFlagTime) ){
37488 this.redrawPlot();
37489 }
37490 if( GeoTemConfig.timeZoom ){
37491 this.zoomSlider.setValue(this.tds.getZoom());
37492 }
37493 return true;
37494 }
37495 */
37496
37497 // handles mousewheel event on the timeplot
37498 var mouseWheelHandler = function(elmt, evt, target) {
37499 if (evt.preventDefault) {
37500 evt.preventDefault();
37501 }
37502 if (plot.dataSources.length == 0) {
37503 return;
37504 }
37505 var delta = 0;
37506 if (!evt)
37507 evt = window.event;
37508 if (evt.wheelDelta) {
37509 delta = evt.wheelDelta / 120;
37510 if (window.opera)
37511 delta = -delta;
37512 } else if (evt.detail) {
37513 delta = -evt.detail / 3;
37514 }
37515 if (delta) {
37516 var x = Math.round(SimileAjax.DOM.getEventRelativeCoordinates(evt, plot.canvas).x);
37517 var time = getCorrelatedTime(x);
37518 plot.zoom(delta, time);
37519 }
37520 }
37521 var timeplotElement = this.timeplot.getElement();
37522 SimileAjax.DOM.registerEvent(timeplotElement, "mousedown", mouseDownHandler);
37523 SimileAjax.DOM.registerEvent(timeplotElement, "mousemove", mouseMoveHandler);
37524 SimileAjax.DOM.registerEvent(timeplotElement, "mousemove", mouseHoverHandler);
37525 SimileAjax.DOM.registerEvent(timeplotElement, "mouseout", mouseOutHandler);
37526 if (GeoTemConfig.mouseWheelZoom) {
37527 //SimileAjax.DOM.registerEvent(timeplotElement, "mousewheel", mouseWheelHandler);
37528 }
37529
37530 this.gui.setHeight();
37531
37532 },
37533
37534 resetOverlay : function() {
37535 this.poles.style.visibility = "hidden";
37536 var plots = this.timeplot._plots;
37537 for (var i = 0; i < plots.length; i++) {
37538 for (var j = 0; j < plots[i].pins.length; j++) {
37539 plots[i].pins[j] = {
37540 height : 0,
37541 count : 0
37542 };
37543 }
37544 }
37545 },
37546
37547 /**
37548 * resets the timeplot to non selection status
37549 */
37550 reset : function() {
37551
37552 this.leftFlagPole.style.visibility = "hidden";
37553 this.rightFlagPole.style.visibility = "hidden";
37554 this.rangeBox.style.visibility = "hidden";
37555 this.leftHandle.style.visibility = "hidden";
37556 this.rightHandle.style.visibility = "hidden";
37557 this.toolbar.style.visibility = "hidden";
37558 this.toolbarAbsoluteDiv.style.visibility = "hidden";
37559 this.cancelButton.style.visibility = "hidden";
37560
37561 var plots = this.timeplot._plots;
37562 for (var i = 0; i < plots.length; i++) {
37563 plots[i].opacityPlot.style.visibility = "hidden";
37564 }
37565 this.resetOverlay();
37566 this.filterBar.reset(false);
37567
37568 var slices = this.tds.timeSlices;
37569 if (slices != undefined) {
37570 for (var i = 0; i < slices.length; i++) {
37571 slices[i].reset();
37572 }
37573 }
37574
37575 this.status = 0;
37576 this.stop();
37577 this.gui.updateAnimationButtons(0);
37578
37579 this.leftFlagPos = null;
37580 this.leftFlagTime = null;
37581 this.rightFlagPos = null;
37582 this.rightFlagTime = null;
37583
37584 this.mouseDownTime = null;
37585 this.mouseUpTime = null;
37586 this.mouseTempTime = null;
37587
37588 this.mouseDownPos = null;
37589 this.mouseUpPos = null;
37590 this.mouseTempPos = null;
37591
37592 if (this.popup) {
37593 this.popup.reset();
37594 this.popupClickDiv.style.visibility = "hidden";
37595 }
37596
37597 },
37598
37599 /**
37600 * sets a pole on the timeplot
37601 * @param {Date} time the time of the specific timeslice
37602 * @param {int[]} the number of selected elements per dataset
37603 */
37604 displayOverlay : function() {
37605 this.poles.style.visibility = "visible";
37606 var cv = this.poles.getElementsByTagName("canvas")[0];
37607 cv.width = this.canvas.width;
37608 cv.height = this.canvas.height;
37609 if (!cv.getContext && G_vmlCanvasManager) {
37610 cv = G_vmlCanvasManager.initElement(cv);
37611 }
37612 var ctx = cv.getContext('2d');
37613 ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
37614 var plots = this.timeplot._plots;
37615 var slices = this.tds.timeSlices;
37616 for (var i = 0; i < slices.length; i++) {
37617 if (this.style == 'bars' && i + 1 == slices.length) {
37618 return;
37619 }
37620 if (slices[i].overlay() == 0) {
37621 continue;
37622 }
37623 var projStacks = slices[i].projStacks;
37624 var time = slices[i].date;
37625 var pos;
37626 if (this.style == 'graph') {
37627 pos = this.timeGeometry.toScreen(time);
37628 } else if (this.style == 'bars') {
37629 var x1 = this.timeGeometry.toScreen(time);
37630 var x2 = this.timeGeometry.toScreen(slices[i + 1].date);
37631 pos = (x1 + x2 ) / 2;
37632 }
37633 var heights = [];
37634 var h = 0;
37635 for (var j = 0; j < projStacks.length; j++) {
37636 var data = plots[j]._dataSource.getData();
37637 for (var k = 0; k < data.times.length; k++) {
37638 if (data.times[k].getTime() == time.getTime()) {
37639 var height = plots[j]._valueGeometry.toScreen(plots[j]._dataSource.getData().values[k]) * projStacks[j].overlay / projStacks[j].value;
37640 heights.push(height);
37641 plots[j].pins[i] = {
37642 height : height,
37643 count : projStacks[j].overlay
37644 };
37645 if (height > h) {
37646 h = height;
37647 }
37648 break;
37649 }
37650 }
37651 }
37652 ctx.fillStyle = "rgb(102,102,102)";
37653 ctx.beginPath();
37654 ctx.rect(pos - 1, this.canvas.height - h, 2, h);
37655 ctx.fill();
37656 for (var j = 0; j < heights.length; j++) {
37657 if (heights[j] > 0) {
37658 var color = GeoTemConfig.getColor(j);
37659 ctx.fillStyle = "rgba(" + color.r1 + "," + color.g1 + "," + color.b1 + ",0.6)";
37660 ctx.beginPath();
37661 ctx.arc(pos, this.canvas.height - heights[j], 2.5, 0, Math.PI * 2, true);
37662 ctx.closePath();
37663 ctx.fill();
37664 }
37665 }
37666 }
37667 },
37668
37669 /**
37670 * updates the timeplot by displaying place poles, after a selection had been executed in another widget
37671 */
37672 highlightChanged : function(timeObjects) {
37673 if( !GeoTemConfig.highlightEvents ){
37674 return;
37675 }
37676 this.resetOverlay();
37677 if (this.selection.valid()) {
37678 if (!this.selection.equal(this)) {
37679 this.tds.setOverlay(GeoTemConfig.mergeObjects(timeObjects, this.selection.getObjects(this)));
37680 } else {
37681 this.tds.setOverlay(timeObjects);
37682 }
37683 } else {
37684 this.tds.setOverlay(timeObjects);
37685 }
37686 this.displayOverlay();
37687 },
37688
37689 /**
37690 * updates the timeplot by displaying place poles, after a selection had been executed in another widget
37691 */
37692 selectionChanged : function(selection) {
37693 if( !GeoTemConfig.selectionEvents ){
37694 return;
37695 }
37696 this.reset();
37697 this.selection = selection;
37698 this.tds.setOverlay(selection.objects);
37699 this.displayOverlay();
37700 },
37701
37702 /**
37703 * returns the approximate left position of a slice inside the overview representation
37704 * @param {Date} time time of the slice
37705 */
37706 getOverviewLeft : function(time) {
37707 var w = this.overview.offsetWidth;
37708 var s = this.tds.earliest().getTime();
37709 var e = this.tds.latest().getTime();
37710 var t = time.getTime();
37711 return Math.round(w * (t - s) / (e - s));
37712 },
37713
37714 /**
37715 * visualizes the overview div (shows viewable part of zoomed timeplot)
37716 */
37717 initOverview : function() {
37718 var labels = this.timeGeometry._grid;
37719 if (labels.length == 0) {
37720 var plot = this;
37721 setTimeout(function() {
37722 plot.initOverview();
37723 }, 10);
37724 return;
37725 }
37726
37727 this.overview.style.width = this.canvas.width + "px";
37728 var left = this.gui.timeplotDiv.offsetLeft;
37729 this.overview.innerHTML = "";
37730 this.overview.style.left = left + "px";
37731
37732 this.overviewRange = document.createElement("div");
37733 this.overviewRange.setAttribute('class', 'overviewRange');
37734 this.overview.appendChild(this.overviewRange);
37735
37736 for (var i = 0; i < labels.length; i++) {
37737 var label = document.createElement("div");
37738 label.setAttribute('class', 'overviewLabel');
37739 label.innerHTML = labels[i].label;
37740 label.style.left = Math.floor(labels[i].x) + "px";
37741 this.overview.appendChild(label);
37742 }
37743
37744 this.updateOverview();
37745 },
37746
37747 /**
37748 * visualizes the labels of the timeplot
37749 */
37750 initLabels : function(labels) {
37751 if (labels.length == 0) {
37752 labels = this.timeGeometry._grid;
37753 if (labels.length == 0) {
37754 var plot = this;
37755 setTimeout(function() {
37756 plot.initLabels([]);
37757 }, 10);
37758 return;
37759 }
37760 }
37761 this.plotLabels.style.width = this.canvas.width + "px";
37762 var left = this.gui.timeplotDiv.offsetLeft;
37763 this.plotLabels.style.left = left + "px";
37764 this.plotLabels.innerHTML = "";
37765 for (var i = 0; i < labels.length; i++) {
37766 var label = document.createElement("div");
37767 label.setAttribute('class', 'plotLabel');
37768 label.innerHTML = labels[i].label;
37769 label.style.left = Math.floor(labels[i].x) + "px";
37770 this.plotLabels.appendChild(label);
37771 }
37772 },
37773
37774 /**
37775 * updates the overview div
37776 */
37777 updateOverview : function() {
37778 if (this.tds.getZoom() > 0) {
37779 this.plotLabels.style.visibility = "hidden";
37780 this.timeGeometry._hideLabels = false;
37781 this.overview.style.visibility = "visible";
37782 this.shiftLeft.style.visibility = "visible";
37783 this.shiftRight.style.visibility = "visible";
37784 var left = this.getOverviewLeft(this.tds.timeSlices[this.tds.leftSlice].date);
37785 var right = this.getOverviewLeft(this.tds.timeSlices[this.tds.rightSlice].date);
37786 this.overviewRange.style.left = left + "px";
37787 this.overviewRange.style.width = (right - left) + "px";
37788 } else {
37789 this.timeGeometry._hideLabels = true;
37790 this.plotLabels.style.visibility = "visible";
37791 this.overview.style.visibility = "hidden";
37792 this.shiftLeft.style.visibility = "hidden";
37793 this.shiftRight.style.visibility = "hidden";
37794 }
37795 },
37796
37797 /**
37798 * returns the time slices which are created by the extended data source
37799 */
37800 getSlices : function() {
37801 return this.tds.timeSlices;
37802 },
37803
37804 timeSelection : function() {
37805 var slices = this.tds.timeSlices;
37806 var ls, rs;
37807 for (var i = 0; i < slices.length; i++) {
37808 if (slices[i].date.getTime() == this.leftFlagTime.getTime())
37809 ls = i;
37810 if (slices[i].date.getTime() == this.rightFlagTime.getTime()) {
37811 if (this.style == 'graph') {
37812 rs = i;
37813 }
37814 if (this.style == 'bars') {
37815 rs = i - 1;
37816 }
37817 }
37818 }
37819 var selectedObjects = [];
37820 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
37821 selectedObjects.push([]);
37822 }
37823 for (var i = 0; i < slices.length; i++) {
37824 if (i >= ls && i <= rs) {
37825 for (var j in slices[i].stacks ) {
37826 selectedObjects[j] = selectedObjects[j].concat(slices[i].stacks[j].elements);
37827 }
37828 }
37829 }
37830 this.selection = new Selection(selectedObjects, this);
37831 this.core.triggerSelection(this.selection);
37832 this.filterBar.reset(true);
37833 },
37834
37835 deselection : function() {
37836 this.reset();
37837 this.selection = new Selection();
37838 this.core.triggerSelection(this.selection);
37839 },
37840
37841 filtering : function() {
37842 for (var i = 0; i < this.datasets.length; i++) {
37843 this.datasets[i].objects = this.selection.objects[i];
37844 }
37845 this.core.triggerRefining(this.datasets);
37846 },
37847
37848 inverseFiltering : function() {
37849 var slices = this.tds.timeSlices;
37850 var ls, rs;
37851 for (var i = 0; i < slices.length; i++) {
37852 if (slices[i].date.getTime() == this.leftFlagTime.getTime())
37853 ls = i;
37854 if (slices[i].date.getTime() == this.rightFlagTime.getTime()) {
37855 if (this.style == 'graph') {
37856 rs = i;
37857 }
37858 if (this.style == 'bars') {
37859 rs = i - 1;
37860 }
37861 }
37862 }
37863 var selectedObjects = [];
37864 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
37865 selectedObjects.push([]);
37866 }
37867 for (var i = 0; i < slices.length; i++) {
37868 if (i >= ls && i <= rs) {
37869 continue;
37870 }
37871 for (var j in slices[i].stacks ) {
37872 selectedObjects[j] = selectedObjects[j].concat(slices[i].stacks[j].elements);
37873 }
37874 }
37875 this.selection = new Selection(selectedObjects, this);
37876 this.filtering();
37877 },
37878
37879 timeHighlight : function(undo) {
37880 if (this.status == 0) {
37881 var s = this.highlightedSlice;
37882 var timeObjects = [];
37883 for (var i = 0; i < this.tds.size(); i++) {
37884 timeObjects.push([]);
37885 }
37886 var add = true;
37887 if (this.leftFlagTime != null) {
37888 if (this.style == 'graph' && s.date >= this.leftFlagTime && s.date <= this.rightFlagTime) {
37889 add = false;
37890 }
37891 if (this.style == 'bars' && s.date >= this.leftFlagTime && s.date < this.rightFlagTime) {
37892 add = false;
37893 }
37894 }
37895 if (!undo && add) {
37896 for (var i in s.stacks ) {
37897 timeObjects[i] = timeObjects[i].concat(s.stacks[i].elements);
37898 }
37899 }
37900 this.core.triggerHighlight(timeObjects);
37901 }
37902 },
37903
37904 timeRefining : function() {
37905 this.core.triggerRefining(this.selection.objects);
37906 },
37907
37908 setStyle : function(style) {
37909 this.style = style;
37910 },
37911
37912 drawLinearPlot : function() {
37913 if ( typeof this.valueGeometry != 'undefined') {
37914 this.valueGeometry.actLinear();
37915 this.timeplot.repaint();
37916 this.resetOpacityPlots();
37917 this.displayOverlay();
37918 }
37919 },
37920
37921 drawLogarithmicPlot : function() {
37922 if ( typeof this.valueGeometry != 'undefined') {
37923 this.valueGeometry.actLogarithmic();
37924 this.timeplot.repaint();
37925 this.resetOpacityPlots();
37926 this.displayOverlay();
37927 }
37928 }
37929 }
37930 /*
37931 * TableConfig.js
37932 *
37933 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
37934 *
37935 * This library is free software; you can redistribute it and/or
37936 * modify it under the terms of the GNU Lesser General Public
37937 * License as published by the Free Software Foundation; either
37938 * version 3 of the License, or (at your option) any later version.
37939 *
37940 * This library is distributed in the hope that it will be useful,
37941 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37942 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37943 * Lesser General Public License for more details.
37944 *
37945 * You should have received a copy of the GNU Lesser General Public
37946 * License along with this library; if not, write to the Free Software
37947 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
37948 * MA 02110-1301 USA
37949 */
37950
37951 /**
37952 * @class TableConfig
37953 * Table Configuration File
37954 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
37955 * @release 1.0
37956 * @release date: 2012-07-27
37957 * @version date: 2012-07-27
37958 */
37959 function TableConfig(options) {
37960
37961 this.options = {
37962 tableWidth : false, // false or desired width css definition for the table
37963 tableHeight : false, // false or desired height css definition for the table
37964 validResultsPerPage : [10, 20, 50, 100], // valid number of elements per page
37965 initialResultsPerPage : 10, // initial number of elements per page
37966 tableSorting : true, // true, if sorting of columns should be possible
37967 tableContentOffset : 250, // maximum display number of characters in a table cell
37968 tableSelectPage : true, // selection of complete table pages
37969 tableSelectAll : false, // selection of complete tables
37970 tableShowSelected : true, // show selected objects only option
37971 tableKeepShowSelected : true, // don't revert to show all on "reset" (e.g. selection)
37972 tableInvertSelection : true, // show invert selection option
37973 tableSelectByText : true, // select objects by full-text search
37974 tableCreateNewFromSelected : true, // create new dataset from selected objects
37975 unselectedCellColor : '#EEE', // color for an unselected row/tab
37976 verticalAlign : 'top', // vertical alignment of the table cells ('top','center','bottom')
37977 };
37978 if ( typeof options != 'undefined') {
37979 $.extend(this.options, options);
37980 }
37981
37982 };
37983 /*
37984 * TableGui.js
37985 *
37986 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
37987 *
37988 * This library is free software; you can redistribute it and/or
37989 * modify it under the terms of the GNU Lesser General Public
37990 * License as published by the Free Software Foundation; either
37991 * version 3 of the License, or (at your option) any later version.
37992 *
37993 * This library is distributed in the hope that it will be useful,
37994 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37995 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37996 * Lesser General Public License for more details.
37997 *
37998 * You should have received a copy of the GNU Lesser General Public
37999 * License along with this library; if not, write to the Free Software
38000 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
38001 * MA 02110-1301 USA
38002 */
38003
38004 /**
38005 * @class TableGui
38006 * Table GUI Implementation
38007 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
38008 * @release 1.0
38009 * @release date: 2012-07-27
38010 * @version date: 2012-07-27
38011 *
38012 * @param {TableWidget} parent table widget object
38013 * @param {HTML object} div parent div to append the table gui
38014 * @param {JSON} options table configuration
38015 */
38016 function TableGui(table, div, options) {
38017
38018 this.tableContainer = div;
38019 if (options.tableWidth) {
38020 this.tableContainer.style.width = options.tableWidth;
38021 }
38022 if (options.tableHeight) {
38023 this.tableContainer.style.height = options.tableHeight;
38024 }
38025 this.tableContainer.style.position = 'relative';
38026
38027 this.tabs = document.createElement('div');
38028 this.tabs.setAttribute('class', 'tableTabs');
38029 div.appendChild(this.tabs);
38030
38031 this.input = document.createElement('div');
38032 this.input.setAttribute('class', 'tableInput');
38033 div.appendChild(this.input);
38034
38035 };
38036 /*
38037 * TableWidget.js
38038 *
38039 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
38040 *
38041 * This library is free software; you can redistribute it and/or
38042 * modify it under the terms of the GNU Lesser General Public
38043 * License as published by the Free Software Foundation; either
38044 * version 3 of the License, or (at your option) any later version.
38045 *
38046 * This library is distributed in the hope that it will be useful,
38047 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38048 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38049 * Lesser General Public License for more details.
38050 *
38051 * You should have received a copy of the GNU Lesser General Public
38052 * License along with this library; if not, write to the Free Software
38053 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
38054 * MA 02110-1301 USA
38055 */
38056
38057 /**
38058 * @class TableWidget
38059 * TableWidget Implementation
38060 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
38061 * @release 1.0
38062 * @release date: 2012-07-27
38063 * @version date: 2012-07-27
38064 *
38065 * @param {TableWrapper} core wrapper for interaction to other widgets
38066 * @param {HTML object} div parent div to append the table widget div
38067 * @param {JSON} options user specified configuration that overwrites options in TableConfig.js
38068 */
38069 TableWidget = function(core, div, options) {
38070
38071 this.core = core;
38072 this.core.setWidget(this);
38073 this.tables = [];
38074 this.tableTabs = [];
38075 this.tableElements = [];
38076 this.tableHash = [];
38077
38078 this.options = (new TableConfig(options)).options;
38079 this.gui = new TableGui(this, div, this.options);
38080 this.filterBar = new FilterBar(this);
38081
38082 }
38083
38084 TableWidget.prototype = {
38085
38086 initWidget : function(data) {
38087 this.datasets = data;
38088
38089 $(this.gui.tabs).empty();
38090 $(this.gui.input).empty();
38091 this.activeTable = undefined;
38092 this.tables = [];
38093 this.tableTabs = [];
38094 this.tableElements = [];
38095 this.tableHash = [];
38096 this.selection = new Selection();
38097 this.filterBar.reset(false);
38098
38099 var tableWidget = this;
38100 var addTab = function(name, index) {
38101 var dataSet = GeoTemConfig.datasets[index];
38102 var tableTab = document.createElement('div');
38103 var tableTabTable = document.createElement('table');
38104 $(tableTab).append(tableTabTable);
38105 var tableTabTableRow = document.createElement('tr');
38106 $(tableTabTable).append(tableTabTableRow);
38107 tableTab.setAttribute('class', 'tableTab');
38108 var c = GeoTemConfig.getColor(index);
38109 tableTab.style.backgroundColor = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
38110 tableTab.onclick = function() {
38111 tableWidget.selectTable(index);
38112 }
38113 var tableNameDiv = document.createElement('div');
38114 $(tableNameDiv).append(name);
38115
38116 if (typeof dataSet.url !== "undefined"){
38117 var tableLinkDiv = document.createElement('a');
38118 tableLinkDiv.title = dataSet.url;
38119 tableLinkDiv.href = dataSet.url;
38120 tableLinkDiv.target = '_';
38121 tableLinkDiv.setAttribute('class', 'externalLink');
38122 $(tableNameDiv).append(tableLinkDiv);
38123 }
38124 $(tableTabTableRow).append($(document.createElement('td')).append(tableNameDiv));
38125
38126 var removeTabDiv = document.createElement('div');
38127 removeTabDiv.setAttribute('class', 'smallButton removeDataset');
38128 removeTabDiv.title = GeoTemConfig.getString('removeDatasetHelp');
38129 removeTabDiv.onclick = $.proxy(function(e) {
38130 GeoTemConfig.removeDataset(index);
38131 //don't let the event propagate to the DIV above
38132 e.stopPropagation();
38133 //discard link click
38134 return(false);
38135 },{index:index});
38136 $(tableTabTableRow).append($(document.createElement('td')).append(removeTabDiv));
38137
38138 if (GeoTemConfig.tableExportDataset){
38139 var exportTabDiv = document.createElement('div');
38140 exportTabDiv.setAttribute('class', 'smallButton exportDataset');
38141 exportTabDiv.title = GeoTemConfig.getString('exportDatasetHelp');
38142 var exportTabForm = document.createElement('form');
38143 //TODO: make this configurable
38144 exportTabForm.action = 'php/download.php';
38145 exportTabForm.method = 'post';
38146 var exportTabHiddenValue = document.createElement('input');
38147 exportTabHiddenValue.name = 'file';
38148 exportTabHiddenValue.type = 'hidden';
38149 exportTabForm.appendChild(exportTabHiddenValue);
38150 exportTabDiv.onclick = $.proxy(function(e) {
38151 $(exportTabHiddenValue).val(GeoTemConfig.createKMLfromDataset(index));
38152 $(exportTabForm).submit();
38153 //don't let the event propagate to the DIV
38154 e.stopPropagation();
38155 //discard link click
38156 return(false);
38157 },{index:index});
38158 exportTabDiv.appendChild(exportTabForm);
38159 $(tableTabTableRow).append($(document.createElement('td')).append(exportTabDiv));
38160 }
38161
38162 if (GeoTemConfig.allowUserShapeAndColorChange){
38163 var dataset = GeoTemConfig.datasets[index];
38164
38165 var changeColorShapeSelect = $("<select></select>");
38166 changeColorShapeSelect.attr("title", GeoTemConfig.getString("colorShapeDatasetHelp"));
38167 changeColorShapeSelect.css("font-size","1.5em");
38168
38169 var currentOptgroup = $("<optgroup label='Current'></optgroup>");
38170 var currentOption = $("<option value='current'></option>");
38171 var color = GeoTemConfig.getColor(index);
38172 currentOption.css("color","rgb("+color.r1+","+color.g1+","+color.b1+")");
38173 currentOption.data("color",{r1:color.r1,g1:color.g1,b1:color.b1,r0:color.r0,g0:color.g0,b0:color.b0});
38174 if (dataset.graphic.shape=="circle"){
38175 currentOption.append("●");
38176 } else if (dataset.graphic.shape=="triangel"){
38177 currentOption.append("▲");
38178 } else if (dataset.graphic.shape=="square"){
38179 if (dataset.graphic.rotation===0){
38180 currentOption.append("■");
38181 } else {
38182 currentOption.append("◆");
38183 }
38184 }
38185 currentOptgroup.append(currentOption);
38186 changeColorShapeSelect.append(currentOptgroup);
38187
38188 var defaultOptgroup = $("<optgroup label='Default'></optgroup>");
38189 var defaultOption = $("<option value='default'></option>");
38190 var color = GeoTemConfig.colors[index];
38191 defaultOption.css("color","rgb("+color.r1+","+color.g1+","+color.b1+")");
38192 defaultOption.data("color",{r1:color.r1,g1:color.g1,b1:color.b1,r0:color.r0,g0:color.g0,b0:color.b0});
38193 defaultOption.append("●");
38194 defaultOptgroup.append(defaultOption);
38195 changeColorShapeSelect.append(defaultOptgroup);
38196
38197 var shapeOptgroup = $("<optgroup label='Shapes'></optgroup>");
38198 shapeOptgroup.append("<option>○</option>");
38199 shapeOptgroup.append("<option>□</option>");
38200 shapeOptgroup.append("<option>◇</option>");
38201 shapeOptgroup.append("<option>△</option>");
38202 changeColorShapeSelect.append(shapeOptgroup);
38203
38204 var colorOptgroup = $("<optgroup label='Colors'></optgroup>");
38205 var red = $("<option style='color:red'>■</option>");
38206 red.data("color",{r1:255,g1:0,b1:0});
38207 colorOptgroup.append(red);
38208 var green = $("<option style='color:green'>■</option>");
38209 green.data("color",{r1:0,g1:255,b1:0});
38210 colorOptgroup.append(green);
38211 var blue = $("<option style='color:blue'>■</option>");
38212 blue.data("color",{r1:0,g1:0,b1:255});
38213 colorOptgroup.append(blue);
38214 var yellow = $("<option style='color:yellow'>■</option>");
38215 yellow.data("color",{r1:255,g1:255,b1:0});
38216 colorOptgroup.append(yellow);
38217 changeColorShapeSelect.append(colorOptgroup);
38218
38219 changeColorShapeSelect.change($.proxy(function(e) {
38220 var selected = changeColorShapeSelect.find("option:selected");
38221
38222 //credits: Pimp Trizkit @ http://stackoverflow.com/a/13542669
38223 function shadeRGBColor(color, percent) {
38224 var f=color.split(","),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
38225 return "rgb("+(Math.round((t-R)*p)+R)+","+(Math.round((t-G)*p)+G)+","+(Math.round((t-B)*p)+B)+")";
38226 }
38227
38228 var color = selected.data("color");
38229
38230 if (typeof color !== "undefined"){
38231 if ( (typeof color.r0 === "undefined") ||
38232 (typeof color.g0 === "undefined") ||
38233 (typeof color.b0 === "undefined") ){
38234 var shadedrgb = shadeRGBColor("rgb("+color.r1+","+color.g1+","+color.b1+")",0.7);
38235 shadedrgb = shadedrgb.replace("rgb(","").replace(")","");
38236 shadedrgb = shadedrgb.split(",");
38237
38238 color.r0 = parseInt(shadedrgb[0]);
38239 color.g0 = parseInt(shadedrgb[1]);
38240 color.b0 = parseInt(shadedrgb[2]);
38241 }
38242 }
38243
38244 var shapeText = selected.text();
38245 var graphic;
38246 if ((shapeText=="■") || (shapeText=="□")){
38247 graphic = {
38248 shape: "square",
38249 rotation: 0
38250 };
38251 } else if ((shapeText=="●") || (shapeText=="○")){
38252 graphic = {
38253 shape: "circle",
38254 rotation: 0
38255 };
38256 } else if ((shapeText=="◆") || (shapeText=="◇")){
38257 graphic = {
38258 shape: "square",
38259 rotation: 45
38260 };
38261 } else if ((shapeText=="▲") || (shapeText=="△")){
38262 graphic = {
38263 shape: "triangle",
38264 rotation: 0
38265 };
38266 }
38267
38268 if (shapeOptgroup.has(selected).length>0){
38269 //shape change
38270 dataset.graphic = graphic;
38271 } else if (colorOptgroup.has(selected).length>0){
38272 //color changed
38273 dataset.color = color;
38274 } else {
38275 //back to default
38276 dataset.graphic = graphic;
38277 dataset.color = color;
38278 }
38279
38280 //reload data
38281 Publisher.Publish('filterData', GeoTemConfig.datasets, null);
38282
38283 //don't let the event propagate to the DIV
38284 e.stopPropagation();
38285 //discard link click
38286 return(false);
38287 },{index:index}));
38288 $(tableTabTableRow).append($(document.createElement('td')).append(changeColorShapeSelect));
38289 }
38290
38291 return tableTab;
38292 }
38293 tableWidget.addTab = addTab;
38294
38295 for (var i in data ) {
38296 this.tableHash.push([]);
38297 var tableTab = addTab(data[i].label, i);
38298 this.gui.tabs.appendChild(tableTab);
38299 this.tableTabs.push(tableTab);
38300 var elements = [];
38301 for (var j in data[i].objects ) {
38302 elements.push(new TableElement(data[i].objects[j]));
38303 this.tableHash[i][data[i].objects[j].index] = elements[elements.length - 1];
38304 }
38305 var table = new Table(elements, this, i);
38306 this.tables.push(table);
38307 this.tableElements.push(elements);
38308 }
38309
38310 if (data.length > 0) {
38311 this.selectTable(0);
38312 }
38313
38314 },
38315
38316 getHeight : function() {
38317 if (this.options.tableHeight) {
38318 return this.gui.tableContainer.offsetHeight - this.gui.tabs.offsetHeight;
38319 }
38320 return false;
38321 },
38322
38323 selectTable : function(index) {
38324 if (this.activeTable != index) {
38325 if ( typeof this.activeTable != 'undefined') {
38326 this.tables[this.activeTable].hide();
38327 var c = GeoTemConfig.getColor(this.activeTable);
38328 this.tableTabs[this.activeTable].style.backgroundColor = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
38329 }
38330 this.activeTable = index;
38331 this.tables[this.activeTable].show();
38332 var c = GeoTemConfig.getColor(this.activeTable);
38333 this.tableTabs[this.activeTable].style.backgroundColor = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
38334 this.core.triggerRise(index);
38335 }
38336
38337 },
38338
38339 highlightChanged : function(objects) {
38340 if( !GeoTemConfig.highlightEvents || (typeof this.tables[this.activeTable] === "undefined")){
38341 return;
38342 }
38343 if( this.tables.length > 0 ){
38344 return;
38345 }
38346 for (var i = 0; i < this.tableElements.length; i++) {
38347 for (var j = 0; j < this.tableElements[i].length; j++) {
38348 this.tableElements[i][j].highlighted = false;
38349 }
38350 }
38351 for (var i = 0; i < objects.length; i++) {
38352 for (var j = 0; j < objects[i].length; j++) {
38353 this.tableHash[i][objects[i][j].index].highlighted = true;
38354 }
38355 }
38356 this.tables[this.activeTable].update();
38357 },
38358
38359 selectionChanged : function(selection) {
38360 if( !GeoTemConfig.selectionEvents || (typeof this.tables[this.activeTable] === "undefined")){
38361 return;
38362 }
38363 this.reset();
38364 if( this.tables.length == 0 ){
38365 return;
38366 }
38367 this.selection = selection;
38368 for (var i = 0; i < this.tableElements.length; i++) {
38369 for (var j = 0; j < this.tableElements[i].length; j++) {
38370 this.tableElements[i][j].selected = false;
38371 this.tableElements[i][j].highlighted = false;
38372 }
38373 }
38374 var objects = selection.getObjects(this);
38375 for (var i = 0; i < objects.length; i++) {
38376 for (var j = 0; j < objects[i].length; j++) {
38377 this.tableHash[i][objects[i][j].index].selected = true;
38378 }
38379 }
38380 this.tables[this.activeTable].reset();
38381 this.tables[this.activeTable].update();
38382 },
38383
38384 triggerHighlight : function(item) {
38385 var selectedObjects = [];
38386 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
38387 selectedObjects.push([]);
38388 }
38389 if ( typeof item != 'undefined') {
38390 selectedObjects[this.activeTable].push(item);
38391 }
38392 this.core.triggerHighlight(selectedObjects);
38393 },
38394
38395 tableSelection : function() {
38396 var selectedObjects = [];
38397 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
38398 selectedObjects.push([]);
38399 }
38400 var valid = false;
38401 for (var i = 0; i < this.tableElements.length; i++) {
38402 for (var j = 0; j < this.tableElements[i].length; j++) {
38403 var e = this.tableElements[i][j];
38404 if (e.selected) {
38405 selectedObjects[i].push(e.object);
38406 valid = true;
38407 }
38408 }
38409 }
38410 this.selection = new Selection();
38411 if (valid) {
38412 this.selection = new Selection(selectedObjects, this);
38413 }
38414 this.core.triggerSelection(this.selection);
38415 this.filterBar.reset(true);
38416 },
38417
38418 deselection : function() {
38419 this.reset();
38420 this.selection = new Selection();
38421 this.core.triggerSelection(this.selection);
38422 },
38423
38424 filtering : function() {
38425 for (var i = 0; i < this.datasets.length; i++) {
38426 this.datasets[i].objects = this.selection.objects[i];
38427 }
38428 this.core.triggerRefining(this.datasets);
38429 },
38430
38431 inverseFiltering : function() {
38432 var selectedObjects = [];
38433 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
38434 selectedObjects.push([]);
38435 }
38436 var valid = false;
38437 for (var i = 0; i < this.tableElements.length; i++) {
38438 for (var j = 0; j < this.tableElements[i].length; j++) {
38439 var e = this.tableElements[i][j];
38440 if (!e.selected) {
38441 selectedObjects[i].push(e.object);
38442 valid = true;
38443 }
38444 }
38445 }
38446 this.selection = new Selection();
38447 if (valid) {
38448 this.selection = new Selection(selectedObjects, this);
38449 }
38450 this.filtering();
38451 },
38452
38453 triggerRefining : function() {
38454 this.core.triggerRefining(this.selection.objects);
38455 },
38456
38457 reset : function() {
38458 this.filterBar.reset(false);
38459 if( this.tables.length > 0 ){
38460 this.tables[this.activeTable].resetElements();
38461 this.tables[this.activeTable].reset();
38462 this.tables[this.activeTable].update();
38463 }
38464 }
38465 }
38466 /*
38467 * Table.js
38468 *
38469 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
38470 *
38471 * This library is free software; you can redistribute it and/or
38472 * modify it under the terms of the GNU Lesser General Public
38473 * License as published by the Free Software Foundation; either
38474 * version 3 of the License, or (at your option) any later version.
38475 *
38476 * This library is distributed in the hope that it will be useful,
38477 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38478 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38479 * Lesser General Public License for more details.
38480 *
38481 * You should have received a copy of the GNU Lesser General Public
38482 * License along with this library; if not, write to the Free Software
38483 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
38484 * MA 02110-1301 USA
38485 */
38486
38487 /**
38488 * @class Table
38489 * Implementation for a single table
38490 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
38491 * @release 1.0
38492 * @release date: 2012-07-27
38493 * @version date: 2012-07-27
38494 *
38495 * @param {Array} elements list of data items
38496 * @param {HTML object} parent div to append the table
38497 * @param {int} id dataset index
38498 */
38499 function Table(elements, parent, id) {
38500
38501 this.elements = elements;
38502 this.showElementsLength = elements.length;
38503 this.parent = parent;
38504 this.id = id;
38505 this.options = parent.options;
38506
38507 this.validResultsPerPage = [10, 20, 50, 100];
38508 this.keyHeaderList = [];
38509 this.initialize();
38510
38511 }
38512
38513 Table.prototype = {
38514
38515 initToolbar : function() {
38516
38517 var table = this;
38518
38519 this.toolbar = document.createElement("table");
38520 this.toolbar.setAttribute('class', 'ddbToolbar');
38521 this.toolbar.style.overflow = 'auto';
38522 this.tableDiv.appendChild(this.toolbar);
38523
38524 var navigation = document.createElement("tr");
38525 this.toolbar.appendChild(navigation);
38526
38527 var selectors = document.createElement("td");
38528 navigation.appendChild(selectors);
38529
38530 if (table.options.tableSelectPage) {
38531 var selectPageItems = true;
38532 this.selectPage = document.createElement('div');
38533 $(this.selectPage).css("float","left");
38534 this.selectPage.setAttribute('class', 'smallButton selectPage');
38535 this.selectPage.title = GeoTemConfig.getString('selectTablePageItemsHelp');
38536 selectors.appendChild(this.selectPage);
38537 this.selectPage.onclick = function() {
38538 selectPageItems = !selectPageItems;
38539 if (selectPageItems) {
38540 var items = 0;
38541 for (var i = table.first; i < table.elements.length; i++) {
38542 table.elements[i].selected = false;
38543 items++;
38544 if (items == table.resultsPerPage) {
38545 break;
38546 }
38547 }
38548 table.selectPage.setAttribute('class', 'smallButton selectPage');
38549 table.selectPage.title = GeoTemConfig.getString('selectTablePageItemsHelp');
38550 } else {
38551 var items = 0;
38552 for (var i = table.first; i < table.elements.length; i++) {
38553 table.elements[i].selected = true;
38554 items++;
38555 if (items == table.resultsPerPage) {
38556 break;
38557 }
38558 }
38559 table.selectPage.setAttribute('class', 'smallButton deselectPage');
38560 table.selectPage.title = GeoTemConfig.getString('deselectTablePageItemsHelp');
38561 }
38562 table.update();
38563 table.parent.tableSelection();
38564 }
38565 }
38566
38567 if (table.options.tableSelectAll) {
38568 var selectAllItems = true;
38569 this.selectAll = document.createElement('div');
38570 this.selectAll.setAttribute('class', 'smallButton selectAll');
38571 $(this.selectAll).css("float","left");
38572 table.selectAll.title = GeoTemConfig.getString('selectAllTableItemsHelp');
38573 selectors.appendChild(this.selectAll);
38574 this.selectAll.onclick = function() {
38575 selectAllItems = !selectAllItems;
38576 if (selectAllItems) {
38577 for (var i = 0; i < table.elements.length; i++) {
38578 table.elements[i].selected = false;
38579 }
38580 table.selectAll.setAttribute('class', 'smallButton selectAll');
38581 table.selectAll.title = GeoTemConfig.getString('selectAllTableItemsHelp');
38582 } else {
38583 for (var i = 0; i < table.elements.length; i++) {
38584 table.elements[i].selected = true;
38585 }
38586 table.selectAll.setAttribute('class', 'smallButton deselectAll');
38587 table.selectAll.title = GeoTemConfig.getString('deselectAllTableItemsHelp');
38588 }
38589 table.update();
38590 table.parent.tableSelection();
38591 }
38592 }
38593
38594 if (table.options.tableInvertSelection) {
38595 this.invertSelection = document.createElement('div');
38596 this.invertSelection.setAttribute('class', 'smallButton invertSelection');
38597 $(this.invertSelection).css("float","left");
38598 table.invertSelection.title = GeoTemConfig.getString('invertSelectionHelp');
38599 selectors.appendChild(this.invertSelection);
38600 this.invertSelection.onclick = function() {
38601 for (var i = 0; i < table.elements.length; i++) {
38602 if (table.elements[i].selected === true)
38603 table.elements[i].selected = false;
38604 else
38605 table.elements[i].selected = true;
38606 }
38607 table.update();
38608 table.parent.tableSelection();
38609 }
38610 }
38611
38612 this.showSelectedItems = false;
38613 if (table.options.tableShowSelected) {
38614 this.showSelected = document.createElement('div');
38615 this.showSelected.setAttribute('class', 'smallButton showSelected');
38616 $(this.showSelected).css("float","left");
38617 table.showSelected.title = GeoTemConfig.getString('showSelectedHelp');
38618 selectors.appendChild(this.showSelected);
38619 this.showSelected.onclick = function() {
38620 table.showSelectedItems = !table.showSelectedItems;
38621 if (table.showSelectedItems) {
38622 table.showElementsLength = 0;
38623 for (var i = 0; i < table.elements.length; i++) {
38624 if (table.elements[i].selected) {
38625 table.showElementsLength++;
38626 }
38627 }
38628 table.showSelected.setAttribute('class', 'smallButton showAll');
38629 // table.selectAll.title = GeoTemConfig.getString('showAllElementsHelp');
38630 } else {
38631 table.showElementsLength = table.elements.length;
38632 table.showSelected.setAttribute('class', 'smallButton showSelected');
38633 // table.selectAll.title = GeoTemConfig.getString('showSelectedHelp');
38634 }
38635 table.updateIndices(table.resultsPerPage);
38636 table.update();
38637 }
38638 }
38639
38640 if (table.options.tableSelectByText) {
38641 this.selectByTextDiv = document.createElement('div');
38642 $(this.selectByTextDiv).css("float","left");
38643 $(this.selectByTextDiv).css("vertical-align", "top");
38644 //TODO: improve appearance (wrong margin)
38645 $(this.selectByTextDiv).css("display", "inline-block");
38646 //create and append the input field
38647 this.selectByTextInput = document.createElement('input');
38648 $(this.selectByTextInput).attr("type","text");
38649 $(this.selectByTextDiv).append(this.selectByTextInput);
38650 //create and append the button
38651 this.selectByTextButton = document.createElement('input');
38652 $(this.selectByTextButton).attr("type","button");
38653 //TODO: add button-image
38654 $(this.selectByTextButton).val("search");
38655 $(this.selectByTextDiv).append(this.selectByTextButton);
38656
38657 table.selectByTextDiv.title = GeoTemConfig.getString('selectByTextHelp');
38658 selectors.appendChild(this.selectByTextDiv);
38659 $(this.selectByTextButton).click($.proxy(function() {
38660 this.selectByText($(this.selectByTextInput).val());
38661 },this));
38662 }
38663
38664 if (table.options.tableCreateNewFromSelected) {
38665 this.createNewFromSelected = document.createElement('div');
38666 this.createNewFromSelected.setAttribute('class', 'smallButton createNewRefined');
38667 $(this.createNewFromSelected).css("float","left");
38668 this.createNewFromSelected.title = GeoTemConfig.getString('createNewFromSelectedHelp');
38669 selectors.appendChild(this.createNewFromSelected);
38670 this.createNewFromSelected.onclick = function() {
38671 var copyID = table.id;
38672 var tableWidget = table.parent;
38673
38674 var newObjects = [];
38675 $(table.elements).each(function(){
38676 if (this.selected)
38677 newObjects.push(this.object);
38678 });
38679
38680 var newDataset = new Dataset();
38681 newDataset.label = tableWidget.datasets[copyID].label + " refined";
38682 newDataset.objects = newObjects;
38683
38684 GeoTemConfig.addDataset(newDataset);
38685 };
38686 }
38687
38688 this.selectors = selectors;
38689
38690 // selectors.style.width = (this.filter.offsetWidth + this.selectAll.offsetWidth + this.selectPage.offsetWidth)+"px";
38691
38692 var results = document.createElement("td");
38693 navigation.appendChild(results);
38694
38695 var pagination = document.createElement("td");
38696 $(pagination).css('float', 'right');
38697 navigation.appendChild(pagination);
38698
38699 this.resultsInfo = document.createElement('div');
38700 this.resultsInfo.setAttribute('class', 'resultsInfo');
38701 results.appendChild(this.resultsInfo);
38702
38703 this.resultsDropdown = document.createElement('div');
38704 this.resultsDropdown.setAttribute('class', 'resultsDropdown');
38705 pagination.appendChild(this.resultsDropdown);
38706 var itemNumbers = [];
38707 var addItemNumber = function(count, index) {
38708 var setItemNumber = function() {
38709 table.updateIndices(count);
38710 table.update();
38711 }
38712 itemNumbers.push({
38713 name : count,
38714 onclick : setItemNumber
38715 });
38716 }
38717 for (var i = 0; i < table.options.validResultsPerPage.length; i++) {
38718 addItemNumber(table.options.validResultsPerPage[i], i);
38719 }
38720 var dropdown = new Dropdown(this.resultsDropdown, itemNumbers, GeoTemConfig.getString('paginationDropdownHelp'));
38721 for (var i = 0; i < table.options.validResultsPerPage.length; i++) {
38722 if (table.options.initialResultsPerPage == table.options.validResultsPerPage[i]) {
38723 dropdown.setEntry(i);
38724 break;
38725 }
38726 }
38727 dropdown.div.title = GeoTemConfig.getString('paginationDropdownHelp');
38728
38729 this.firstPage = document.createElement('div');
38730 this.firstPage.setAttribute('class', 'paginationButton');
38731 this.firstPage.title = GeoTemConfig.getString('paginationFirsPageHelp');
38732
38733 pagination.appendChild(this.firstPage);
38734 this.firstPage.onclick = function() {
38735 if (table.page != 0) {
38736 table.page = 0;
38737 table.update();
38738 }
38739 }
38740
38741 this.previousPage = document.createElement('div');
38742 this.previousPage.setAttribute('class', 'paginationButton');
38743 this.previousPage.title = GeoTemConfig.getString('paginationPreviousPageHelp');
38744 pagination.appendChild(this.previousPage);
38745 this.previousPage.onclick = function() {
38746 if (table.page > 0) {
38747 table.page--;
38748 table.update();
38749 }
38750 }
38751
38752 this.pageInfo = document.createElement('div');
38753 this.pageInfo.setAttribute('class', 'pageInfo');
38754 pagination.appendChild(this.pageInfo);
38755
38756 this.nextPage = document.createElement('div');
38757 this.nextPage.setAttribute('class', 'paginationButton');
38758 this.nextPage.title = GeoTemConfig.getString('paginationNextPageHelp');
38759 pagination.appendChild(this.nextPage);
38760 this.nextPage.onclick = function() {
38761 if (table.page < table.pages - 1) {
38762 table.page++;
38763 table.update();
38764 }
38765 }
38766
38767 this.lastPage = document.createElement('div');
38768 this.lastPage.setAttribute('class', 'paginationButton');
38769 this.lastPage.title = GeoTemConfig.getString('paginationLastPageHelp');
38770 pagination.appendChild(this.lastPage);
38771 this.lastPage.onclick = function() {
38772 if (table.page != table.pages - 1) {
38773 table.page = table.pages - 1;
38774 table.update();
38775 }
38776 }
38777
38778 this.input = document.createElement("div");
38779 this.input.style.overflow = 'auto';
38780 this.tableDiv.appendChild(this.input);
38781
38782 this.elementList = document.createElement("table");
38783 this.elementList.setAttribute('class', 'resultList');
38784 this.input.appendChild(this.elementList);
38785 var height = this.parent.getHeight();
38786 if (height) {
38787 this.input.style.height = (height - pagination.offsetHeight) + 'px';
38788 this.input.style.overflowY = 'auto';
38789 }
38790
38791 this.elementListHeader = document.createElement("tr");
38792 this.elementList.appendChild(this.elementListHeader);
38793
38794 if (GeoTemConfig.allowFilter) {
38795 var cell = document.createElement('th');
38796 this.elementListHeader.appendChild(cell);
38797 }
38798
38799 //Bottom pagination elements
38800 this.bottomToolbar = document.createElement("table");
38801 this.bottomToolbar.setAttribute('class', 'ddbToolbar');
38802 this.bottomToolbar.style.overflow = 'auto';
38803 this.tableDiv.appendChild(this.bottomToolbar);
38804
38805 var bottomNavigation = document.createElement("tr");
38806 this.bottomToolbar.appendChild(bottomNavigation);
38807
38808 var bottomPagination = document.createElement("td");
38809 bottomNavigation.appendChild(bottomPagination);
38810
38811 this.bottomLastPage = document.createElement('div');
38812 this.bottomLastPage.setAttribute('class', 'paginationButton');
38813 this.bottomLastPage.title = GeoTemConfig.getString('paginationLastPageHelp');
38814 $(this.bottomLastPage).css('float', 'right');
38815 bottomPagination.appendChild(this.bottomLastPage);
38816 this.bottomLastPage.onclick = function() {
38817 if (table.page != table.pages - 1) {
38818 table.page = table.pages - 1;
38819 table.update();
38820 }
38821 }
38822
38823 this.bottomNextPage = document.createElement('div');
38824 this.bottomNextPage.setAttribute('class', 'paginationButton');
38825 this.bottomNextPage.title = GeoTemConfig.getString('paginationNextPageHelp');
38826 $(this.bottomNextPage).css('float', 'right');
38827 bottomPagination.appendChild(this.bottomNextPage);
38828 this.bottomNextPage.onclick = function() {
38829 if (table.page < table.pages - 1) {
38830 table.page++;
38831 table.update();
38832 }
38833 }
38834
38835 this.bottomPageInfo = document.createElement('div');
38836 this.bottomPageInfo.setAttribute('class', 'pageInfo');
38837 $(this.bottomPageInfo).css('float', 'right');
38838 bottomPagination.appendChild(this.bottomPageInfo);
38839
38840 this.bottomPreviousPage = document.createElement('div');
38841 this.bottomPreviousPage.setAttribute('class', 'paginationButton');
38842 this.bottomPreviousPage.title = GeoTemConfig.getString('paginationPreviousPageHelp');
38843 $(this.bottomPreviousPage).css('float', 'right');
38844 bottomPagination.appendChild(this.bottomPreviousPage);
38845 this.bottomPreviousPage.onclick = function() {
38846 if (table.page > 0) {
38847 table.page--;
38848 table.update();
38849 }
38850 }
38851
38852 this.bottomFirstPage = document.createElement('div');
38853 this.bottomFirstPage.setAttribute('class', 'paginationButton');
38854 this.bottomFirstPage.title = GeoTemConfig.getString('paginationFirsPageHelp');
38855 $(this.bottomFirstPage).css('float', 'right');
38856 bottomPagination.appendChild(this.bottomFirstPage);
38857 this.bottomFirstPage.onclick = function() {
38858 if (table.page != 0) {
38859 table.page = 0;
38860 table.update();
38861 }
38862 }
38863
38864 if ( typeof (this.elements[0]) == 'undefined') {
38865 return;
38866 }
38867
38868 var ascButtons = [];
38869 var descButtons = [];
38870 var clearButtons = function() {
38871 for (var i in ascButtons ) {
38872 ascButtons[i].setAttribute('class', 'sort sortAscDeactive');
38873 }
38874 for (var i in descButtons ) {
38875 descButtons[i].setAttribute('class', 'sort sortDescDeactive');
38876 }
38877 }
38878 var addSortButton = function(key) {
38879 table.keyHeaderList.push(key);
38880 var cell = document.createElement('th');
38881 table.elementListHeader.appendChild(cell);
38882 var sortAsc = document.createElement('div');
38883 var sortDesc = document.createElement('div');
38884 var span = document.createElement('div');
38885 span.setAttribute('class', 'headerLabel');
38886 span.innerHTML = key;
38887 cell.appendChild(sortDesc);
38888 cell.appendChild(span);
38889 cell.appendChild(sortAsc);
38890 sortAsc.setAttribute('class', 'sort sortAscDeactive');
38891 sortAsc.title = GeoTemConfig.getString('sortAZHelp');
38892 sortDesc.setAttribute('class', 'sort sortDescDeactive');
38893 sortDesc.title = GeoTemConfig.getString('sortZAHelp');
38894 ascButtons.push(sortAsc);
38895 descButtons.push(sortDesc);
38896 sortAsc.onclick = function() {
38897 clearButtons();
38898 sortAsc.setAttribute('class', 'sort sortAscActive');
38899 table.sortAscending(key);
38900 table.update();
38901 }
38902 sortDesc.onclick = function() {
38903 clearButtons();
38904 sortDesc.setAttribute('class', 'sort sortDescActive');
38905 table.sortDescending(key);
38906 table.update();
38907 }
38908 }
38909 for (var key in this.elements[0].object.tableContent) {
38910 addSortButton(key);
38911 }
38912 },
38913
38914 sortAscending : function(key) {
38915 var sortFunction = function(e1, e2) {
38916 if (e1.object.tableContent[key] < e2.object.tableContent[key]) {
38917 return -1;
38918 }
38919 return 1;
38920 }
38921 this.elements.sort(sortFunction);
38922 },
38923
38924 sortDescending : function(key) {
38925 var sortFunction = function(e1, e2) {
38926 if (e1.object.tableContent[key] > e2.object.tableContent[key]) {
38927 return -1;
38928 }
38929 return 1;
38930 }
38931 this.elements.sort(sortFunction);
38932 },
38933
38934 selectByText : function(text) {
38935 //deselect all elements
38936 $(this.elements).each(function(){
38937 this.selected = false;
38938 });
38939
38940 var selectedCount = 0;
38941 $(this.elements).filter(function(index){
38942 return this.object.contains(text);
38943 }).each(function(){
38944 this.selected = true;
38945 selectedCount++;
38946 });
38947
38948 //only show selected elements
38949 this.showSelectedItems = true;
38950 this.showElementsLength = selectedCount;
38951 this.showSelected.setAttribute('class', 'smallButton showAll');
38952
38953 this.update();
38954 this.parent.tableSelection();
38955 },
38956
38957 setPagesText : function() {
38958 var infoText = GeoTemConfig.getString('pageInfo');
38959 infoText = infoText.replace('PAGES_ID', this.pages);
38960 infoText = infoText.replace('PAGE_ID', this.page + 1);
38961 this.pageInfo.innerHTML = infoText;
38962 this.bottomPageInfo.innerHTML = infoText;
38963 },
38964
38965 setResultsText : function() {
38966 if (this.elements.length == 0) {
38967 this.resultsInfo.innerHTML = '0 Results';
38968 } else {
38969 var infoText = GeoTemConfig.getString('resultsInfo');
38970 var first = this.page * this.resultsPerPage + 1;
38971 var last = (this.page + 1 == this.pages ) ? this.showElementsLength : first + this.resultsPerPage - 1;
38972 infoText = infoText.replace('RESULTS_FROM_ID', first);
38973 infoText = infoText.replace('RESULTS_TO_ID', last);
38974 infoText = infoText.replace('RESULTS_ID', this.showElementsLength);
38975 this.resultsInfo.innerHTML = infoText;
38976 }
38977 },
38978
38979 updateIndices : function(rpp) {
38980 if ( typeof this.resultsPerPage == 'undefined') {
38981 this.page = 0;
38982 this.resultsPerPage = 0;
38983 }
38984 var index = this.page * this.resultsPerPage;
38985 this.resultsPerPage = rpp;
38986 if (this.showSelectedItems) {
38987 index = 0;
38988 }
38989 this.pages = Math.floor(this.showElementsLength / this.resultsPerPage);
38990 if (this.showElementsLength % this.resultsPerPage != 0) {
38991 this.pages++;
38992 }
38993 this.page = Math.floor(index / this.resultsPerPage);
38994 },
38995
38996 update : function() {
38997 var table = this;
38998 $(this.elementList).find("tr:gt(0)").remove();
38999 if (this.page == 0) {
39000 this.previousPage.setAttribute('class', 'paginationButton previousPageDisabled');
39001 this.firstPage.setAttribute('class', 'paginationButton firstPageDisabled');
39002 this.bottomPreviousPage.setAttribute('class', 'paginationButton previousPageDisabled');
39003 this.bottomFirstPage.setAttribute('class', 'paginationButton firstPageDisabled');
39004 } else {
39005 this.previousPage.setAttribute('class', 'paginationButton previousPageEnabled');
39006 this.firstPage.setAttribute('class', 'paginationButton firstPageEnabled');
39007 this.bottomPreviousPage.setAttribute('class', 'paginationButton previousPageEnabled');
39008 this.bottomFirstPage.setAttribute('class', 'paginationButton firstPageEnabled');
39009 }
39010 if (this.page == this.pages - 1) {
39011 this.nextPage.setAttribute('class', 'paginationButton nextPageDisabled');
39012 this.lastPage.setAttribute('class', 'paginationButton lastPageDisabled');
39013 this.bottomNextPage.setAttribute('class', 'paginationButton nextPageDisabled');
39014 this.bottomLastPage.setAttribute('class', 'paginationButton lastPageDisabled');
39015 } else {
39016 this.nextPage.setAttribute('class', 'paginationButton nextPageEnabled');
39017 this.lastPage.setAttribute('class', 'paginationButton lastPageEnabled');
39018 this.bottomNextPage.setAttribute('class', 'paginationButton nextPageEnabled');
39019 this.bottomLastPage.setAttribute('class', 'paginationButton lastPageEnabled');
39020 }
39021 this.setPagesText();
39022 this.setResultsText();
39023 if (this.showSelectedItems) {
39024 var start = this.page * this.resultsPerPage;
39025 var items = 0;
39026 for (var i = 0; i < this.elements.length; i++) {
39027 if (items == start) {
39028 this.first = i;
39029 break;
39030 }
39031 if (this.elements[i].selected) {
39032 items++;
39033 }
39034 }
39035 } else {
39036 this.first = this.page * this.resultsPerPage;
39037 }
39038 //this.last = ( this.page + 1 == this.pages ) ? this.elements.length : this.first + this.resultsPerPage;
39039 var c = GeoTemConfig.getColor(this.id);
39040 var itemSet = [];
39041 var clearDivs = function() {
39042 for (var i = 0; i < itemSet.length; i++) {
39043 if (!itemSet[i].e.selected) {
39044 itemSet[i].e.highlighted = false;
39045 $(itemSet[i].div).css('background-color', table.options.unselectedCellColor);
39046 }
39047 }
39048 }
39049 var setHighlight = function(item, div) {
39050 var enter = function() {
39051 clearDivs();
39052 if (!item.selected) {
39053 item.highlighted = true;
39054 $(div).css('background-color', 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')');
39055 table.parent.triggerHighlight(item.object);
39056 }
39057 }
39058 var leave = function() {
39059 clearDivs();
39060 if (!item.selected) {
39061 table.parent.triggerHighlight();
39062 }
39063 }
39064 $(div).hover(enter, leave);
39065 $(div).mousemove(function() {
39066 if (!item.selected && !item.highlighted) {
39067 item.highlighted = true;
39068 $(div).css('background-color', 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')');
39069 table.parent.triggerHighlight(item.object);
39070 }
39071 });
39072 }
39073 var setSelection = function(item, div, checkbox) {
39074 var click = function(e) {
39075 var checked = $(checkbox).is(':checked');
39076 if (checked) {
39077 item.selected = true;
39078 item.highlighted = false;
39079 } else {
39080 item.selected = false;
39081 item.highlighted = true;
39082 }
39083 //if( e.target == div ){
39084 // $(checkbox).attr('checked', !checked);
39085 //}
39086 table.parent.tableSelection();
39087 }
39088 //$(div).click(click);
39089 $(checkbox).click(click);
39090 }
39091 this.checkboxes = [];
39092 var items = 0;
39093 for (var i = this.first; i < this.elements.length; i++) {
39094 var e = this.elements[i];
39095 //vhz because of an error
39096 if ( typeof (e) == "undefined") {
39097 continue;
39098 }
39099 if (this.showSelectedItems && !e.selected) {
39100 continue;
39101 }
39102 var itemRow = $("<tr/>").appendTo(this.elementList);
39103 if (GeoTemConfig.allowFilter) {
39104 var checkColumn = $("<td/>").appendTo(itemRow);
39105 var checkbox = $("<input type='checkbox'/>").appendTo(checkColumn);
39106 $(checkbox).attr('checked', e.selected);
39107 }
39108 var makeSubtext = function(cell, text) {
39109 var subtext = text.substring(0, table.options.tableContentOffset);
39110 subtext = subtext.substring(0, subtext.lastIndexOf(' '));
39111 subtext += ' ... ';
39112 var textDiv = $("<div style='display:inline-block;'/>").appendTo(cell);
39113 $(textDiv).html(subtext);
39114 var show = false;
39115 var fullDiv = $("<div style='display:inline-block;'><a href='javascript:void(0)'>\>\></a></div>").appendTo(cell);
39116 $(fullDiv).click(function() {
39117 show = !show;
39118 if (show) {
39119 $(textDiv).html(text);
39120 $(fullDiv).html('<a href="javascript:void(0)">\<\<</a>');
39121 } else {
39122 $(textDiv).html(subtext);
39123 $(fullDiv).html('<a href="javascript:void(0)">\>\></a>');
39124 }
39125 });
39126 }
39127 for (var k = 0; k < table.keyHeaderList.length; k++) {
39128 var key = table.keyHeaderList[k];
39129 //vhz
39130 var text = e.object.tableContent[key];
39131 if (typeof text === "undefined")
39132 text = "";
39133 var cell = $("<td></td>").appendTo(itemRow);
39134
39135 //align the elements (if unset: "center")
39136 if (typeof table.options.verticalAlign !== "undefined"){
39137 if (table.options.verticalAlign === "top")
39138 $(cell).attr("valign","top");
39139 else if (table.options.verticalAlign === "center")
39140 $(cell).attr("valign","center");
39141 else if (table.options.verticalAlign === "bottom")
39142 $(cell).attr("valign","bottom");
39143 }
39144
39145 if (table.options.tableContentOffset && text.length < table.options.tableContentOffset) {
39146 $(cell).html(text);
39147 } else {
39148 makeSubtext(cell, text);
39149 }
39150 }
39151 if (e.selected || e.highlighted) {
39152 $(itemRow).css('background-color', 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')');
39153 } else {
39154 $(itemRow).css('background-color', table.options.unselectedCellColor);
39155 }
39156 itemSet.push({
39157 e : e,
39158 div : itemRow
39159 });
39160 setHighlight(e, itemRow);
39161 if (GeoTemConfig.allowFilter) {
39162 setSelection(e, itemRow, checkbox);
39163 this.checkboxes.push(checkbox);
39164 $(checkColumn).css('text-align', 'center');
39165 }
39166 items++;
39167 if (items == this.resultsPerPage) {
39168 break;
39169 }
39170 }
39171 },
39172
39173 show : function() {
39174 if (GeoTemConfig.allowFilter) {
39175 this.parent.filterBar.appendTo(this.selectors);
39176 }
39177 this.tableDiv.style.display = "block";
39178 },
39179
39180 hide : function() {
39181 this.tableDiv.style.display = "none";
39182 },
39183
39184 resetElements : function() {
39185 for (var i = 0; i < this.elements.length; i++) {
39186 this.elements[i].selected = false;
39187 this.elements[i].highlighted = false;
39188 }
39189 },
39190
39191 reset : function() {
39192 if (!this.options.tableKeepShowSelected){
39193 this.showSelectedItems = false;
39194 this.showElementsLength = this.elements.length;
39195 this.showSelected.setAttribute('class', 'smallButton showSelected');
39196 }
39197 this.updateIndices(this.resultsPerPage);
39198 },
39199
39200 initialize : function() {
39201
39202 this.tableDiv = document.createElement("div");
39203 this.tableDiv.setAttribute('class', 'singleTable');
39204 this.parent.gui.input.appendChild(this.tableDiv);
39205
39206 this.initToolbar();
39207
39208 this.tableDiv.style.display = 'none';
39209 this.updateIndices(this.options.initialResultsPerPage);
39210
39211 this.update();
39212
39213 }
39214 }
39215
39216 function TableElement(object) {
39217
39218 this.object = object;
39219 this.selected = false;
39220 this.highlighted = false;
39221
39222 }
39223 /*
39224 * Dataloader.js
39225 *
39226 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
39227 *
39228 * This library is free software; you can redistribute it and/or
39229 * modify it under the terms of the GNU Lesser General Public
39230 * License as published by the Free Software Foundation; either
39231 * version 3 of the License, or (at your option) any later version.
39232 *
39233 * This library is distributed in the hope that it will be useful,
39234 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39235 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39236 * Lesser General Public License for more details.
39237 *
39238 * You should have received a copy of the GNU Lesser General Public
39239 * License along with this library; if not, write to the Free Software
39240 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
39241 * MA 02110-1301 USA
39242 */
39243
39244 /**
39245 * @class Dataloader
39246 * Implementation for a Dataloader UI
39247 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
39248 *
39249 * @param {HTML object} parent div to append the Dataloader
39250 */
39251 function Dataloader(parent) {
39252
39253 this.dataLoader = this;
39254
39255 this.parent = parent;
39256 this.options = parent.options;
39257
39258 this.initialize();
39259 }
39260
39261 Dataloader.prototype = {
39262
39263 show : function() {
39264 this.dataloaderDiv.style.display = "block";
39265 },
39266
39267 hide : function() {
39268 this.dataloaderDiv.style.display = "none";
39269 },
39270
39271 initialize : function() {
39272
39273 this.addStaticLoader();
39274 this.addLocalStorageLoader();
39275 this.addKMLLoader();
39276 this.addKMZLoader();
39277 this.addCSVLoader();
39278 this.addLocalKMLLoader();
39279 this.addLocalCSVLoader();
39280 this.addLocalXLSXLoader();
39281
39282 // trigger change event on the select so
39283 // that only the first loader div will be shown
39284 $(this.parent.gui.loaderTypeSelect).change();
39285 },
39286
39287 getFileName : function(url) {
39288 var fileName = $.url(url).attr('file');
39289 if ( (typeof fileName === "undefined") || (fileName.length === 0) ){
39290 fileName = $.url(url).attr('path');
39291 //startsWith and endsWith defined in SIMILE Ajax (string.js)
39292 while (fileName.endsWith("/")){
39293 fileName = fileName.substr(0,fileName.length-1);
39294 }
39295 if (fileName.length > 1)
39296 fileName = fileName.substr(fileName.lastIndexOf("/")+1);
39297 else
39298 fileName = "unnamed dataset";
39299 }
39300 return fileName;
39301 },
39302
39303 distributeDataset : function(dataSet) {
39304 GeoTemConfig.addDataset(dataSet);
39305 },
39306
39307 distributeDatasets : function(datasets) {
39308 GeoTemConfig.addDatasets(datasets);
39309 },
39310
39311 addStaticLoader : function() {
39312 if (this.options.staticKML.length > 0){
39313 $(this.parent.gui.loaderTypeSelect).append("<option value='StaticLoader'>Static Data</option>");
39314
39315 this.StaticLoaderTab = document.createElement("div");
39316 $(this.StaticLoaderTab).attr("id","StaticLoader");
39317
39318 this.staticKMLList = document.createElement("select");
39319 $(this.StaticLoaderTab).append(this.staticKMLList);
39320
39321 var staticKMLList = this.staticKMLList;
39322 var isFirstHeader = true;
39323 $(this.options.staticKML).each(function(){
39324 var label = this.label;
39325 var url = this.url;
39326 var header = this.header;
39327 if (typeof header !== "undefined"){
39328 if (!isFirstHeader)
39329 $(staticKMLList).append("</optgroup>");
39330 $(staticKMLList).append("<optgroup label='"+header+"'>");
39331 isFirstHeader = false;
39332 } else
39333 $(staticKMLList).append("<option value='"+url+"'> "+label+"</option>");
39334 });
39335 //close last optgroup (if there were any)
39336 if (!isFirstHeader)
39337 $(staticKMLList).append("</optgroup>");
39338
39339 this.loadStaticKMLButton = document.createElement("button");
39340 $(this.loadStaticKMLButton).text("load");
39341 $(this.StaticLoaderTab).append(this.loadStaticKMLButton);
39342
39343 $(this.loadStaticKMLButton).click($.proxy(function(){
39344 var kmlURL = $(this.staticKMLList).find(":selected").attr("value");
39345 if (kmlURL.length === 0)
39346 return;
39347 var origURL = kmlURL;
39348 var fileName = this.getFileName(kmlURL);
39349 if (typeof GeoTemConfig.proxy != 'undefined')
39350 kmlURL = GeoTemConfig.proxy + kmlURL;
39351 var kml = GeoTemConfig.getKml(kmlURL);
39352 if ((typeof kml !== "undefined") && (kml != null)) {
39353 var dataSet = new Dataset(GeoTemConfig.loadKml(kml), fileName, origURL);
39354
39355 if (dataSet != null)
39356 this.distributeDataset(dataSet);
39357 } else
39358 alert("Could not load file.");
39359 },this));
39360
39361 $(this.parent.gui.loaders).append(this.StaticLoaderTab);
39362 }
39363 },
39364
39365 addKMLLoader : function() {
39366 $(this.parent.gui.loaderTypeSelect).append("<option value='KMLLoader'>KML File URL</option>");
39367
39368 this.KMLLoaderTab = document.createElement("div");
39369 $(this.KMLLoaderTab).attr("id","KMLLoader");
39370
39371 this.kmlURL = document.createElement("input");
39372 $(this.kmlURL).attr("type","text");
39373 $(this.KMLLoaderTab).append(this.kmlURL);
39374
39375 this.loadKMLButton = document.createElement("button");
39376 $(this.loadKMLButton).text("load KML");
39377 $(this.KMLLoaderTab).append(this.loadKMLButton);
39378
39379 $(this.loadKMLButton).click($.proxy(function(){
39380 var kmlURL = $(this.kmlURL).val();
39381 if (kmlURL.length === 0)
39382 return;
39383 var origURL = kmlURL;
39384 var fileName = this.getFileName(kmlURL);
39385 if (typeof GeoTemConfig.proxy != 'undefined')
39386 kmlURL = GeoTemConfig.proxy + kmlURL;
39387 var kml = GeoTemConfig.getKml(kmlURL);
39388 if ((typeof kml !== "undefined") && (kml != null)) {
39389 var dataSet = new Dataset(GeoTemConfig.loadKml(kml), fileName, origURL);
39390
39391 if (dataSet != null)
39392 this.distributeDataset(dataSet);
39393 } else
39394 alert("Could not load file.");
39395 },this));
39396
39397 $(this.parent.gui.loaders).append(this.KMLLoaderTab);
39398 },
39399
39400 addKMZLoader : function() {
39401 $(this.parent.gui.loaderTypeSelect).append("<option value='KMZLoader'>KMZ File URL</option>");
39402
39403 this.KMZLoaderTab = document.createElement("div");
39404 $(this.KMZLoaderTab).attr("id","KMZLoader");
39405
39406 this.kmzURL = document.createElement("input");
39407 $(this.kmzURL).attr("type","text");
39408 $(this.KMZLoaderTab).append(this.kmzURL);
39409
39410 this.loadKMZButton = document.createElement("button");
39411 $(this.loadKMZButton).text("load KMZ");
39412 $(this.KMZLoaderTab).append(this.loadKMZButton);
39413
39414 $(this.loadKMZButton).click($.proxy(function(){
39415
39416 var dataLoader = this;
39417
39418 var kmzURL = $(this.kmzURL).val();
39419 if (kmzURL.length === 0)
39420 return;
39421 var origURL = kmzURL;
39422 var fileName = dataLoader.getFileName(kmzURL);
39423 if (typeof GeoTemConfig.proxy != 'undefined')
39424 kmzURL = GeoTemConfig.proxy + kmzURL;
39425
39426 GeoTemConfig.getKmz(kmzURL, function(kmlArray){
39427 $(kmlArray).each(function(){
39428 var dataSet = new Dataset(GeoTemConfig.loadKml(this), fileName, origURL);
39429
39430 if (dataSet != null)
39431 dataLoader.distributeDataset(dataSet);
39432 });
39433 });
39434 },this));
39435
39436 $(this.parent.gui.loaders).append(this.KMZLoaderTab);
39437 },
39438
39439 addCSVLoader : function() {
39440 $(this.parent.gui.loaderTypeSelect).append("<option value='CSVLoader'>CSV File URL</option>");
39441
39442 this.CSVLoaderTab = document.createElement("div");
39443 $(this.CSVLoaderTab).attr("id","CSVLoader");
39444
39445 this.csvURL = document.createElement("input");
39446 $(this.csvURL).attr("type","text");
39447 $(this.CSVLoaderTab).append(this.csvURL);
39448
39449 this.loadCSVButton = document.createElement("button");
39450 $(this.loadCSVButton).text("load CSV");
39451 $(this.CSVLoaderTab).append(this.loadCSVButton);
39452
39453 $(this.loadCSVButton).click($.proxy(function(){
39454 var dataLoader = this;
39455
39456 var csvURL = $(this.csvURL).val();
39457 if (csvURL.length === 0)
39458 return;
39459 var origURL = csvURL;
39460 var fileName = dataLoader.getFileName(csvURL);
39461 if (typeof GeoTemConfig.proxy != 'undefined')
39462 csvURL = GeoTemConfig.proxy + csvURL;
39463 GeoTemConfig.getCsv(csvURL, function(json){
39464 if ((typeof json !== "undefined") && (json.length > 0)) {
39465 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, origURL);
39466
39467 if (dataSet != null)
39468 dataLoader.distributeDataset(dataSet);
39469 } else
39470 alert("Could not load file.");
39471 });
39472 },this));
39473
39474 $(this.parent.gui.loaders).append(this.CSVLoaderTab);
39475 },
39476
39477 addLocalKMLLoader : function() {
39478 $(this.parent.gui.loaderTypeSelect).append("<option value='LocalKMLLoader'>local KML File</option>");
39479
39480 this.localKMLLoaderTab = document.createElement("div");
39481 $(this.localKMLLoaderTab).attr("id","LocalKMLLoader");
39482
39483 this.kmlFile = document.createElement("input");
39484 $(this.kmlFile).attr("type","file");
39485 $(this.localKMLLoaderTab).append(this.kmlFile);
39486
39487 this.loadLocalKMLButton = document.createElement("button");
39488 $(this.loadLocalKMLButton).text("load KML");
39489 $(this.localKMLLoaderTab).append(this.loadLocalKMLButton);
39490
39491 $(this.loadLocalKMLButton).click($.proxy(function(){
39492 var filelist = $(this.kmlFile).get(0).files;
39493 if (filelist.length > 0){
39494 var file = filelist[0];
39495 var fileName = file.name;
39496 var reader = new FileReader();
39497
39498 reader.onloadend = ($.proxy(function(theFile) {
39499 return function(e) {
39500 var dataSet = new Dataset(GeoTemConfig.loadKml($.parseXML(reader.result)), fileName);
39501 if (dataSet != null)
39502 this.distributeDataset(dataSet);
39503 };
39504 }(file),this));
39505
39506 reader.readAsText(file);
39507 }
39508 },this));
39509
39510 $(this.parent.gui.loaders).append(this.localKMLLoaderTab);
39511 },
39512
39513 addLocalCSVLoader : function() {
39514 $(this.parent.gui.loaderTypeSelect).append("<option value='LocalCSVLoader'>local CSV File</option>");
39515
39516 this.localCSVLoaderTab = document.createElement("div");
39517 $(this.localCSVLoaderTab).attr("id","LocalCSVLoader");
39518
39519 this.csvFile = document.createElement("input");
39520 $(this.csvFile).attr("type","file");
39521 $(this.localCSVLoaderTab).append(this.csvFile);
39522
39523 this.loadLocalCSVButton = document.createElement("button");
39524 $(this.loadLocalCSVButton).text("load CSV");
39525 $(this.localCSVLoaderTab).append(this.loadLocalCSVButton);
39526
39527 $(this.loadLocalCSVButton).click($.proxy(function(){
39528 var filelist = $(this.csvFile).get(0).files;
39529 if (filelist.length > 0){
39530 var file = filelist[0];
39531 var fileName = file.name;
39532 var reader = new FileReader();
39533
39534 reader.onloadend = ($.proxy(function(theFile) {
39535 return function(e) {
39536 var json = GeoTemConfig.convertCsv(reader.result);
39537 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName);
39538 if (dataSet != null)
39539 this.distributeDataset(dataSet);
39540 };
39541 }(file),this));
39542
39543 reader.readAsText(file);
39544 }
39545 },this));
39546
39547 $(this.parent.gui.loaders).append(this.localCSVLoaderTab);
39548 },
39549
39550 addLocalStorageLoader : function() {
39551 var dataLoader = this;
39552 this.localStorageLoaderTab = document.createElement("div");
39553 $(this.localStorageLoaderTab).attr("id","LocalStorageLoader");
39554
39555 var localDatasets = document.createElement("select");
39556 $(this.localStorageLoaderTab).append(localDatasets);
39557
39558 var localStorageDatasetCount = 0;
39559 for(var key in localStorage){
39560 //TODO: this is a somewhat bad idea, as it is used in multiple widgets.
39561 //A global GeoTemCo option "prefix" could be better. But still..
39562 if (key.startsWith("GeoBrowser_dataset_")){
39563 localStorageDatasetCount++;
39564 var label = key.substring("GeoBrowser_dataset_".length);
39565 var url = key;
39566 $(localDatasets).append("<option value='"+url+"'>"+decodeURIComponent(label)+"</option>");
39567 }
39568 }
39569
39570 //only show if there are datasets
39571 if (localStorageDatasetCount > 0)
39572 $(this.parent.gui.loaderTypeSelect).append("<option value='LocalStorageLoader'>browser storage</option>");
39573
39574 this.loadLocalStorageButton = document.createElement("button");
39575 $(this.loadLocalStorageButton).text("load");
39576 $(this.localStorageLoaderTab).append(this.loadLocalStorageButton);
39577
39578 $(this.loadLocalStorageButton).click($.proxy(function(){
39579 var fileKey = $(localDatasets).find(":selected").attr("value");
39580 if (fileKey.length === 0)
39581 return;
39582 var csv = $.remember({name:fileKey});
39583 //TODO: this is a somewhat bad idea, as it is used in multiple widgets.
39584 //A global GeoTemCo option "prefix" could be better. But still..
39585 var fileName = decodeURIComponent(fileKey.substring("GeoBrowser_dataset_".length));
39586 var json = GeoTemConfig.convertCsv(csv);
39587 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, fileKey, "local");
39588 if (dataSet != null)
39589 dataLoader.distributeDataset(dataSet);
39590 },this));
39591
39592 $(this.parent.gui.loaders).append(this.localStorageLoaderTab);
39593 },
39594
39595 addLocalXLSXLoader : function() {
39596 //taken from http://oss.sheetjs.com/js-xlsx/
39597 var fixdata = function(data) {
39598 var o = "", l = 0, w = 10240;
39599 for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
39600 o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(o.length)));
39601 return o;
39602 }
39603
39604 $(this.parent.gui.loaderTypeSelect).append("<option value='LocalXLSXLoader'>local XLS/XLSX File</option>");
39605
39606 this.LocalXLSXLoader = document.createElement("div");
39607 $(this.LocalXLSXLoader).attr("id","LocalXLSXLoader");
39608
39609 this.xlsxFile = document.createElement("input");
39610 $(this.xlsxFile).attr("type","file");
39611 $(this.LocalXLSXLoader).append(this.xlsxFile);
39612
39613 this.loadLocalXLSXButton = document.createElement("button");
39614 $(this.loadLocalXLSXButton).text("load XLS/XLSX");
39615 $(this.LocalXLSXLoader).append(this.loadLocalXLSXButton);
39616
39617 $(this.loadLocalXLSXButton).click($.proxy(function(){
39618 var filelist = $(this.xlsxFile).get(0).files;
39619 if (filelist.length > 0){
39620 var file = filelist[0];
39621 var fileName = file.name;
39622 var reader = new FileReader();
39623
39624 reader.onloadend = ($.proxy(function(theFile) {
39625 return function(e) {
39626 var workbook;
39627 var json;
39628 if (fileName.toLowerCase().indexOf("xlsx")!=-1){
39629 workbook = XLSX.read(btoa(fixdata(reader.result)), {type: 'base64'});
39630 var csv = XLSX.utils.sheet_to_csv(workbook.Sheets[workbook.SheetNames[0]]);
39631 var json = GeoTemConfig.convertCsv(csv);
39632 } else {
39633 workbook = XLS.read(btoa(fixdata(reader.result)), {type: 'base64'});
39634 var csv = XLS.utils.sheet_to_csv(workbook.Sheets[workbook.SheetNames[0]]);
39635 var json = GeoTemConfig.convertCsv(csv);
39636 }
39637
39638 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName);
39639 if (dataSet != null)
39640 this.distributeDataset(dataSet);
39641 };
39642 }(file),this));
39643
39644 reader.readAsArrayBuffer(file);
39645 }
39646 },this));
39647
39648 $(this.parent.gui.loaders).append(this.LocalXLSXLoader);
39649 },
39650 };
39651 /*
39652 * DataloaderConfig.js
39653 *
39654 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
39655 *
39656 * This library is free software; you can redistribute it and/or
39657 * modify it under the terms of the GNU Lesser General Public
39658 * License as published by the Free Software Foundation; either
39659 * version 3 of the License, or (at your option) any later version.
39660 *
39661 * This library is distributed in the hope that it will be useful,
39662 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39663 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39664 * Lesser General Public License for more details.
39665 *
39666 * You should have received a copy of the GNU Lesser General Public
39667 * License along with this library; if not, write to the Free Software
39668 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
39669 * MA 02110-1301 USA
39670 */
39671
39672 /**
39673 * @class DataloaderConfig
39674 * Dataloader Configuration File
39675 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
39676 */
39677 function DataloaderConfig(options) {
39678
39679 this.options = {
39680 staticKML : [
39681 // {header: "header label"},
39682 // {label: "Johann Wolfgang von Goethe", url:"http://.../goethe.kml" },
39683 ]
39684 };
39685 if ( typeof options != 'undefined') {
39686 $.extend(this.options, options);
39687 }
39688
39689 };
39690 /*
39691 * DataloaderGui.js
39692 *
39693 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
39694 *
39695 * This library is free software; you can redistribute it and/or
39696 * modify it under the terms of the GNU Lesser General Public
39697 * License as published by the Free Software Foundation; either
39698 * version 3 of the License, or (at your option) any later version.
39699 *
39700 * This library is distributed in the hope that it will be useful,
39701 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39702 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39703 * Lesser General Public License for more details.
39704 *
39705 * You should have received a copy of the GNU Lesser General Public
39706 * License along with this library; if not, write to the Free Software
39707 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
39708 * MA 02110-1301 USA
39709 */
39710
39711 /**
39712 * @class DataloaderGui
39713 * Dataloader GUI Implementation
39714 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
39715 *
39716 * @param {DataloaderWidget} parent Dataloader widget object
39717 * @param {HTML object} div parent div to append the Dataloader gui
39718 * @param {JSON} options Dataloader configuration
39719 */
39720 function DataloaderGui(dataloader, div, options) {
39721
39722 var dataloaderGui = this;
39723
39724 this.dataloaderContainer = div;
39725 this.dataloaderContainer.style.position = 'relative';
39726
39727 this.loaderTypeSelect = document.createElement("select");
39728 div.appendChild(this.loaderTypeSelect);
39729
39730 this.loaders = document.createElement("div");
39731 div.appendChild(this.loaders);
39732
39733 $(this.loaderTypeSelect).change(function(){
39734 var activeLoader = $(this).val();
39735 $(dataloaderGui.loaders).find("div").each(function(){
39736 if ($(this).attr("id") == activeLoader)
39737 $(this).show();
39738 else
39739 $(this).hide();
39740 });
39741 });
39742 };
39743 /*
39744 * DataloaderWidget.js
39745 *
39746 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
39747 *
39748 * This library is free software; you can redistribute it and/or
39749 * modify it under the terms of the GNU Lesser General Public
39750 * License as published by the Free Software Foundation; either
39751 * version 3 of the License, or (at your option) any later version.
39752 *
39753 * This library is distributed in the hope that it will be useful,
39754 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39755 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39756 * Lesser General Public License for more details.
39757 *
39758 * You should have received a copy of the GNU Lesser General Public
39759 * License along with this library; if not, write to the Free Software
39760 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
39761 * MA 02110-1301 USA
39762 */
39763
39764 /**
39765 * @class DataloaderWidget
39766 * DataloaderWidget Implementation
39767 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
39768 *
39769 * @param {WidgetWrapper} core wrapper for interaction to other widgets
39770 * @param {HTML object} div parent div to append the Dataloader widget div
39771 * @param {JSON} options user specified configuration that overwrites options in DataloaderConfig.js
39772 */
39773 DataloaderWidget = function(core, div, options) {
39774
39775 this.core = core;
39776 this.core.setWidget(this);
39777
39778 this.options = (new DataloaderConfig(options)).options;
39779 this.gui = new DataloaderGui(this, div, this.options);
39780
39781 this.dataLoader = new Dataloader(this);
39782
39783 this.datasets = [];
39784 }
39785
39786 DataloaderWidget.prototype = {
39787
39788 initWidget : function() {
39789
39790 var dataloaderWidget = this;
39791 },
39792
39793 highlightChanged : function(objects) {
39794 if( !GeoTemConfig.highlightEvents ){
39795 return;
39796 }
39797 },
39798
39799 selectionChanged : function(selection) {
39800 if( !GeoTemConfig.selectionEvents ){
39801 return;
39802 }
39803 },
39804
39805 triggerHighlight : function(item) {
39806 },
39807
39808 tableSelection : function() {
39809 },
39810
39811 deselection : function() {
39812 },
39813
39814 filtering : function() {
39815 },
39816
39817 inverseFiltering : function() {
39818 },
39819
39820 triggerRefining : function() {
39821 },
39822
39823 reset : function() {
39824 },
39825
39826 loadRenames : function(){
39827 //load (optional!) attribute renames
39828 //each rename param is {latitude:..,longitude:..,place:..,date:..,timeSpanBegin:..,timeSpanEnd:..}
39829 //examples:
39830 // &rename1={"latitude":"lat1","longitude":"lon1"}
39831 // &rename2=[{"latitude":"lat1","longitude":"lon1"},{"latitude":"lat2","longitude":"lon2"}]
39832 var dataLoaderWidget = this;
39833 var datasets = dataLoaderWidget.datasets;
39834 $.each($.url().param(),function(paramName, paramValue){
39835 if (paramName.toLowerCase().startsWith("rename")){
39836 var datasetID = parseInt(paramName.replace(/\D/g,''));
39837 var dataset;
39838 if (isNaN(datasetID)){
39839 var dataset;
39840 for (datasetID in datasets){
39841 break;
39842 }
39843 }
39844 dataset = datasets[datasetID];
39845
39846 if (typeof dataset === "undefined")
39847 return;
39848
39849 var renameFunc = function(index,latAttr,lonAttr,placeAttr,dateAttr,timespanBeginAttr,
39850 timespanEndAttr,indexAttr){
39851 var renameArray = [];
39852
39853 if (typeof index === "undefined"){
39854 index = 0;
39855 }
39856
39857 if ((typeof latAttr !== "undefined") && (typeof lonAttr !== "undefined")){
39858 renameArray.push({
39859 oldColumn:latAttr,
39860 newColumn:"locations["+index+"].latitude"
39861 });
39862 renameArray.push({
39863 oldColumn:lonAttr,
39864 newColumn:"locations["+index+"].longitude"
39865 });
39866 }
39867
39868 if (typeof placeAttr !== "undefined"){
39869 renameArray.push({
39870 oldColumn:placeAttr,
39871 newColumn:"locations["+index+"].place"
39872 });
39873 }
39874
39875 if (typeof dateAttr !== "undefined"){
39876 renameArray.push({
39877 oldColumn:dateAttr,
39878 newColumn:"dates["+index+"]"
39879 });
39880 }
39881
39882 if ((typeof timespanBeginAttr !== "undefined") &&
39883 (typeof timespanEndAttr !== "undefined")){
39884 renameArray.push({
39885 oldColumn:timespanBeginAttr,
39886 newColumn:"tableContent[TimeSpan:begin]"
39887 });
39888 renameArray.push({
39889 oldColumn:timespanEndAttr,
39890 newColumn:"tableContent[TimeSpan:end]"
39891 });
39892 }
39893
39894 if (typeof indexAttr !== "undefined"){
39895 renameArray.push({
39896 oldColumn:indexAttr,
39897 newColumn:"index"
39898 });
39899 }
39900
39901 GeoTemConfig.renameColumns(dataset,renameArray);
39902 };
39903
39904 var renames = JSON.parse(paramValue);
39905
39906 if (renames instanceof Array){
39907 for (var i=0; i < renames.length; i++){
39908 renameFunc(i,renames[i].latitude,renames[i].longitude,renames[i].place,renames[i].date,
39909 renames[i].timeSpanBegin,renames[i].timeSpanEnd,renames[i].index);
39910 }
39911 } else {
39912 renameFunc(0,renames.latitude,renames.longitude,renames.place,renames.date,
39913 renames.timeSpanBegin,renames.timeSpanEnd,renames.index);
39914 }
39915 }
39916 });
39917 },
39918
39919 loadFilters : function(){
39920 //load (optional!) filters
39921 //those will create a new(!) dataset, that only contains the filtered IDs
39922 var dataLoaderWidget = this;
39923 var datasets = dataLoaderWidget.datasets;
39924 $.each($.url().param(),function(paramName, paramValue){
39925 //startsWith and endsWith defined in SIMILE Ajax (string.js)
39926 if (paramName.toLowerCase().startsWith("filter")){
39927 var datasetID = parseInt(paramName.replace(/\D/g,''));
39928 var dataset;
39929 if (isNaN(datasetID)){
39930 var dataset;
39931 for (datasetID in datasets){
39932 break;
39933 }
39934 }
39935 dataset = datasets[datasetID];
39936
39937 if (typeof dataset === "undefined")
39938 return;
39939
39940 var filterValues = function(paramValue){
39941 var filter = JSON.parse(paramValue);
39942 var filteredObjects = [];
39943 for(var i = 0; i < dataset.objects.length; i++){
39944 var dataObject = dataset.objects[i];
39945 if ($.inArray(dataObject.index,filter) != -1){
39946 filteredObjects.push(dataObject);
39947 }
39948 }
39949 var filteredDataset = new Dataset(filteredObjects, dataset.label + " (filtered)", dataset.url, dataset.type);
39950 datasets.push(filteredDataset);
39951 }
39952
39953 if (paramValue instanceof Array){
39954 for (var i=0; i < paramValue.length; i++){
39955 filterValues(paramValue[i]);
39956 }
39957 } else {
39958 filterValues(paramValue);
39959 }
39960
39961 }
39962 });
39963 },
39964
39965 loadColors : function(){
39966 //Load the (optional!) dataset colors
39967 var dataLoaderWidget = this;
39968 var datasets = dataLoaderWidget.datasets;
39969 $.each($.url().param(),function(paramName, paramValue){
39970 if (paramName.toLowerCase().startsWith("color")){
39971 //color is 1-based, index is 0-based!
39972 var datasetID = parseInt(paramName.replace(/\D/g,''));
39973 if (datasets.length > datasetID){
39974 if (typeof datasets[datasetID].color === "undefined"){
39975 var color = new Object();
39976 var colorsSelectedUnselected = paramValue.split(",");
39977 if (colorsSelectedUnselected.length > 2)
39978 return;
39979
39980 var color1 = colorsSelectedUnselected[0];
39981 if (color1.length != 6)
39982 return;
39983
39984 color.r1 = parseInt(color1.substr(0,2),16);
39985 color.g1 = parseInt(color1.substr(2,2),16);
39986 color.b1 = parseInt(color1.substr(4,2),16);
39987
39988 //check if a unselected color is given
39989 if (colorsSelectedUnselected.length == 2){
39990 var color0 = colorsSelectedUnselected[1];
39991 if (color0.length != 6)
39992 return;
39993
39994 color.r0 = parseInt(color0.substr(0,2),16);
39995 color.g0 = parseInt(color0.substr(2,2),16);
39996 color.b0 = parseInt(color0.substr(4,2),16);
39997 } else {
39998 //if not: use the selected color "halved"
39999 color.r0 = Math.round(color.r1/2);
40000 color.g0 = Math.round(color.g1/2);
40001 color.b0 = Math.round(color.b1/2);
40002 }
40003
40004 datasets[datasetID].color = color;
40005 }
40006 }
40007 }
40008 });
40009 },
40010
40011 loadFromURL : function() {
40012 var dataLoaderWidget = this;
40013 dataLoaderWidget.datasets = [];
40014 //using jQuery-URL-Parser (https://github.com/skruse/jQuery-URL-Parser)
40015 var datasets = dataLoaderWidget.datasets;
40016 var parametersHash = $.url().param();
40017 var parametersArray = [];
40018 $.each(parametersHash,function(paramName, paramValue){
40019 parametersArray.push({paramName:paramName, paramValue:paramValue});
40020 });
40021
40022 var parseParam = function(paramNr){
40023
40024 if (paramNr==parametersArray.length){
40025 dataLoaderWidget.loadRenames();
40026 dataLoaderWidget.loadFilters();
40027 dataLoaderWidget.loadColors();
40028
40029 //delete undefined entries in the array
40030 //(can happen if the sequence given in the URL is not complete
40031 // e.g. kml0=..,kml2=..)
40032 //this also reorders the array, starting with 0
40033 var tempDatasets = [];
40034 for(var index in datasets){
40035 if (datasets[index] instanceof Dataset){
40036 tempDatasets.push(datasets[index]);
40037 }
40038 }
40039 datasets = tempDatasets;
40040
40041 if (datasets.length > 0){
40042 dataLoaderWidget.dataLoader.distributeDatasets(datasets);
40043 }
40044 return;
40045 }
40046
40047 var paramName = parametersArray[paramNr].paramName;
40048 var paramValue = parametersArray[paramNr].paramValue;
40049
40050 var datasetID = parseInt(paramName.replace(/\D/g,''));
40051
40052 //startsWith and endsWith defined in SIMILE Ajax (string.js)
40053 var fileName = dataLoaderWidget.dataLoader.getFileName(paramValue);
40054 var origURL = paramValue;
40055 if (typeof GeoTemConfig.proxy != 'undefined')
40056 paramValue = GeoTemConfig.proxy + paramValue;
40057 if (paramName.toLowerCase().startsWith("kml")){
40058 GeoTemConfig.getKml(paramValue, function(kmlDoc){
40059 var dataSet = new Dataset(GeoTemConfig.loadKml(kmlDoc), fileName, origURL);
40060 if (dataSet != null){
40061 if (!isNaN(datasetID)){
40062 datasets[datasetID] = dataSet;
40063 } else {
40064 datasets.push(dataSet);
40065 }
40066 }
40067 setTimeout(function(){parseParam(paramNr+1)},1);
40068 });
40069 }
40070 else if (paramName.toLowerCase().startsWith("csv")){
40071 GeoTemConfig.getCsv(paramValue,function(json){
40072 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, origURL);
40073 if (dataSet != null){
40074 if (!isNaN(datasetID)){
40075 datasets[datasetID] = dataSet;
40076 } else {
40077 datasets.push(dataSet);
40078 }
40079 }
40080 setTimeout(function(){parseParam(paramNr+1)},1);
40081 });
40082 }
40083 else if (paramName.toLowerCase().startsWith("json")){
40084 GeoTemConfig.getJson(paramValue,function(json ){
40085 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, origURL);
40086 if (dataSet != null){
40087 if (!isNaN(datasetID)){
40088 datasets[datasetID] = dataSet;
40089 } else {
40090 datasets.push(dataSet);
40091 }
40092 }
40093 setTimeout(function(){parseParam(paramNr+1)},1);
40094 });
40095 }
40096 else if (paramName.toLowerCase().startsWith("local")){
40097 var csv = $.remember({name:encodeURIComponent(origURL)});
40098 //TODO: this is a bad idea and will be changed upon having a better
40099 //usage model for local stored data
40100 var fileName = origURL.substring("GeoBrowser_dataset_".length);
40101 var json = GeoTemConfig.convertCsv(csv);
40102 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, origURL, "local");
40103 if (dataSet != null){
40104 if (!isNaN(datasetID)){
40105 datasets[datasetID] = dataSet;
40106 } else {
40107 datasets.push(dataSet);
40108 }
40109 }
40110 setTimeout(function(){parseParam(paramNr+1)},1);
40111 } else if (paramName.toLowerCase().startsWith("xls")){
40112 GeoTemConfig.getBinary(paramValue,function(binaryData){
40113 var data = new Uint8Array(binaryData);
40114 var arr = new Array();
40115 for(var i = 0; i != data.length; ++i){
40116 arr[i] = String.fromCharCode(data[i]);
40117 }
40118
40119 var workbook;
40120 var json;
40121 if (paramName.toLowerCase().startsWith("xlsx")){
40122 workbook = XLSX.read(arr.join(""), {type:"binary"});
40123 var csv = XLSX.utils.sheet_to_csv(workbook.Sheets[workbook.SheetNames[0]]);
40124 var json = GeoTemConfig.convertCsv(csv);
40125 } else {
40126 workbook = XLS.read(arr.join(""), {type:"binary"});
40127 var csv = XLS.utils.sheet_to_csv(workbook.Sheets[workbook.SheetNames[0]]);
40128 var json = GeoTemConfig.convertCsv(csv);
40129 }
40130
40131 var dataSet = new Dataset(GeoTemConfig.loadJson(json), fileName, origURL);
40132 if (dataSet != null){
40133 if (!isNaN(datasetID)){
40134 datasets[datasetID] = dataSet;
40135 } else {
40136 datasets.push(dataSet);
40137 }
40138 }
40139 setTimeout(function(){parseParam(paramNr+1)},1);
40140 });
40141 } else {
40142 setTimeout(function(){parseParam(paramNr+1)},1);
40143 }
40144 };
40145
40146 if (parametersArray.length>0){
40147 parseParam(0)
40148 }
40149 }
40150 };
40151 /*
40152 * FuzzyTimelineConfig.js
40153 *
40154 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
40155 *
40156 * This library is free software; you can redistribute it and/or
40157 * modify it under the terms of the GNU Lesser General Public
40158 * License as published by the Free Software Foundation; either
40159 * version 3 of the License, or (at your option) any later version.
40160 *
40161 * This library is distributed in the hope that it will be useful,
40162 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40163 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40164 * Lesser General Public License for more details.
40165 *
40166 * You should have received a copy of the GNU Lesser General Public
40167 * License along with this library; if not, write to the Free Software
40168 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
40169 * MA 02110-1301 USA
40170 */
40171
40172 /**
40173 * @class FuzzyTimelineConfig
40174 * FuzzyTimeline Configuration File
40175 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
40176 */
40177 function FuzzyTimelineConfig(options) {
40178
40179 this.options = {
40180 //TODO: experiment with number of ticks, 150 seems to be ok for now
40181 maxBars : 50,
40182 maxDensityTicks : 150,
40183 /*drawing modes:
40184 * fuzzy - weight is distributed over all spans an object overlaps, so that the sum remains the weight,
40185 * stacking - every span that on object overlaps gets the complete weight (limited by the amount the span is overlapped, e.g. first span and last might get less)
40186 */
40187 timelineMode : 'stacking',
40188 showRangePiechart : false,
40189 backgroundColor : "#EEEEEE",
40190 showYAxis : true,
40191 //whether time-spans that "enlargen" the plot are allowed
40192 //if set to true, a span that creates more "bars" than fit on the screen
40193 //will lead to a width-increase of the chart (and a scroll bar appears)
40194 showAllPossibleSpans : true,
40195 };
40196 if ( typeof options != 'undefined') {
40197 $.extend(this.options, options);
40198 }
40199
40200 };
40201 /*
40202 * FuzzyTimelineDensity.js
40203 *
40204 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
40205 *
40206 * This library is free software; you can redistribute it and/or
40207 * modify it under the terms of the GNU Lesser General Public
40208 * License as published by the Free Software Foundation; either
40209 * version 3 of the License, or (at your option) any later version.
40210 *
40211 * This library is distributed in the hope that it will be useful,
40212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40213 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40214 * Lesser General Public License for more details.
40215 *
40216 * You should have received a copy of the GNU Lesser General Public
40217 * License along with this library; if not, write to the Free Software
40218 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
40219 * MA 02110-1301 USA
40220 */
40221
40222 /**
40223 * @class FuzzyTimelineDensity
40224 * Implementation for a fuzzy time-ranges density plot
40225 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
40226 *
40227 * @param {HTML object} parent div to append the FuzzyTimeline
40228 */
40229 function FuzzyTimelineDensity(parent,div) {
40230
40231 this.index;
40232 this.fuzzyTimeline = this;
40233 this.singleTickWidth;
40234 this.singleTickCenter = function(){return this.singleTickWidth/2;};
40235 //contains all data
40236 this.datasetsPlot;
40237 this.datasetsHash;
40238 this.highlightedDatasetsPlot;
40239 this.yValMin;
40240 this.yValMax;
40241 this.displayType;
40242 //contains selected data
40243 this.selected = undefined;
40244 //contains the last selected "date"
40245 this.highlighted;
40246
40247 this.parent = parent;
40248 this.div = div;
40249 this.options = parent.options;
40250 this.plot;
40251 this.maxTickCount = this.options.maxDensityTicks;
40252
40253 this.datasets;
40254 }
40255
40256 FuzzyTimelineDensity.prototype = {
40257
40258 initialize : function(datasets) {
40259 var density = this;
40260
40261 density.datasets = datasets;
40262 density.selected = [];
40263 },
40264
40265 createPlot : function(data){
40266 density = this;
40267 var chartData = [];
40268
40269 chartData.push([density.parent.overallMin,0]);
40270 $.each(data, function(name,val){
40271 var tickCenterTime = density.parent.overallMin+name*density.singleTickWidth+density.singleTickCenter();
40272 var dateObj = moment(tickCenterTime);
40273 chartData.push([dateObj,val]);
40274 });
40275 var maxPlotedDate = chartData[chartData.length-1][0];
40276 if (density.parent.overallMax > maxPlotedDate){
40277 chartData.push([density.parent.overallMax,0]);
40278 } else {
40279 chartData.push([maxPlotedDate+1,0]);
40280 }
40281
40282
40283
40284 return chartData;
40285 },
40286
40287 //uniform distribution (UD)
40288 createUDData : function(datasets) {
40289 var density = this;
40290 var plots = [];
40291 var objectHashes = [];
40292 $(datasets).each(function(){
40293 var chartDataCounter = new Object();
40294 var objectHash = new Object();
40295
40296 for (var i = 0; i < density.tickCount; i++){
40297 chartDataCounter[i]=0;
40298 }
40299 //check if we got "real" datasets, or just array of objects
40300 var datasetObjects = this;
40301 if (typeof this.objects !== "undefined")
40302 datasetObjects = this.objects;
40303 $(datasetObjects).each(function(){
40304 var ticks = density.parent.getTicks(this, density.singleTickWidth);
40305 if (typeof ticks !== "undefined"){
40306 var exactTickCount =
40307 ticks.firstTickPercentage+
40308 ticks.lastTickPercentage+
40309 (ticks.lastTick-ticks.firstTick-1);
40310 for (var i = ticks.firstTick; i <= ticks.lastTick; i++){
40311 var weight = 0;
40312 //calculate the weight for each span, that the object overlaps
40313 if (density.parent.options.timelineMode == 'fuzzy'){
40314 //in fuzzy mode, each span gets just a fraction of the complete weight
40315 if (i == ticks.firstTick)
40316 weight = this.weight * ticks.firstTickPercentage/exactTickCount;
40317 else if (i == ticks.lastTick)
40318 weight = this.weight * ticks.lastTickPercentage/exactTickCount;
40319 else
40320 weight = this.weight * 1/exactTickCount;
40321 } else if (density.parent.options.timelineMode == 'stacking'){
40322 //in stacking mode each span gets the same amount.
40323 //(besides first and last..)
40324 if (i == ticks.firstTick)
40325 weight = this.weight * ticks.firstTickPercentage;
40326 else if (i == ticks.lastTick)
40327 weight = this.weight * ticks.lastTickPercentage;
40328 else
40329 weight = this.weight;
40330 }
40331
40332 chartDataCounter[i] += weight;
40333 //add this object to the hash
40334 if (typeof objectHash[i] === "undefined")
40335 objectHash[i] = [];
40336 objectHash[i].push(this);
40337 }
40338 }
40339 });
40340
40341 //scale according to selected type
40342 chartDataCounter = density.parent.scaleData(chartDataCounter);
40343
40344 var udChartData = density.createPlot(chartDataCounter);
40345 if (udChartData.length > 0)
40346 plots.push(udChartData);
40347
40348 objectHashes.push(objectHash);
40349 });
40350
40351 return {plots:plots, hashs:objectHashes};
40352 },
40353
40354 showPlot : function() {
40355 var density = this;
40356 var plot = density.datasetsPlot;
40357 var highlight_select_plot = $.merge([],plot);
40358
40359 //see if there are selected/highlighted values
40360 if (density.highlightedDatasetsPlot instanceof Array){
40361 //check if plot is some other - external - graph
40362 if (plot === density.datasetsPlot)
40363 highlight_select_plot = $.merge(highlight_select_plot,density.highlightedDatasetsPlot);
40364 }
40365
40366 var axisFormatString = "%Y";
40367 var tooltipFormatString = "YYYY";
40368 if (density.singleTickWidth<60*1000){
40369 axisFormatString = "%Y/%m/%d %H:%M:%S";
40370 tooltipFormatString = "YYYY/MM/DD HH:mm:ss";
40371 } else if (density.singleTickWidth<60*60*1000) {
40372 axisFormatString = "%Y/%m/%d %H:%M";
40373 tooltipFormatString = "YYYY/MM/DD HH:mm";
40374 } else if (density.singleTickWidth<24*60*60*1000){
40375 axisFormatString = "%Y/%m/%d %H";
40376 tooltipFormatString = "YYYY/MM/DD HH";
40377 } else if (density.singleTickWidth<31*24*60*60*1000){
40378 axisFormatString = "%Y/%m/%d";
40379 tooltipFormatString = "YYYY/MM/DD";
40380 } else if (density.singleTickWidth<12*31*24*60*60*1000){
40381 axisFormatString = "%Y/%m";
40382 tooltipFormatString = "YYYY/MM";
40383 }
40384
40385 //credits: Pimp Trizkit @ http://stackoverflow.com/a/13542669
40386 function shadeRGBColor(color, percent) {
40387 var f=color.split(","),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
40388 return "rgb("+(Math.round((t-R)*p)+R)+","+(Math.round((t-G)*p)+G)+","+(Math.round((t-B)*p)+B)+")";
40389 }
40390
40391 //credits: Tupak Goliam @ http://stackoverflow.com/a/3821786
40392 var drawLines = function(plot, ctx) {
40393 var data = plot.getData();
40394 var axes = plot.getAxes();
40395 var offset = plot.getPlotOffset();
40396 for (var i = 0; i < data.length; i++) {
40397 var series = data[i];
40398 var lineWidth = 1;
40399
40400 for (var j = 0; j < series.data.length-1; j++) {
40401 var d = (series.data[j]);
40402 var d2 = (series.data[j+1]);
40403
40404 var x = offset.left + axes.xaxis.p2c(d[0]);
40405 var y = offset.top + axes.yaxis.p2c(d[1]);
40406
40407 var x2 = offset.left + axes.xaxis.p2c(d2[0]);
40408 var y2 = offset.top + axes.yaxis.p2c(d2[1]);
40409
40410 //hide lines that "connect" 0 and 0
40411 //essentially blanking out the 0 values
40412 if ((d[1]==0)&&(d2[1]==0)){
40413 continue;
40414 }
40415
40416 ctx.strokeStyle=series.color;
40417 ctx.lineWidth = lineWidth;
40418 ctx.beginPath();
40419 ctx.moveTo(x,y);
40420 ctx.lineTo(x2,y2);
40421
40422 //add shadow (esp. to make background lines more visible)
40423 ctx.shadowColor = shadeRGBColor(series.color,-0.3);
40424 ctx.shadowBlur=1;
40425 ctx.shadowOffsetX = 1;
40426 ctx.shadowOffsetY = 1;
40427
40428 ctx.stroke();
40429 }
40430 }
40431 };
40432
40433 var options = {
40434 series:{
40435 //width:0 because line is drawn in own routine above
40436 //but everything else (data points, shadow) should be drawn
40437 lines:{show: true, lineWidth: 0, shadowSize: 0},
40438 },
40439 grid: {
40440 hoverable: true,
40441 clickable: true,
40442 backgroundColor: density.parent.options.backgroundColor,
40443 borderWidth: 0,
40444 minBorderMargin: 0,
40445 },
40446 legend: {
40447 },
40448 tooltip: true,
40449 tooltipOpts: {
40450 content: function(label, xval, yval, flotItem){
40451 highlightString = moment(xval-density.singleTickCenter()).format(tooltipFormatString) + " - " +
40452 moment(xval+density.singleTickCenter()).format(tooltipFormatString) + " : ";
40453 //(max.)2 Nachkomma-Stellen von y-Wert anzeigen
40454 highlightString += Math.round(yval*100)/100;
40455
40456 return highlightString;
40457 }
40458 },
40459 selection: {
40460 mode: "x"
40461 },
40462 xaxis: {
40463 mode: "time",
40464 timeformat:axisFormatString,
40465 min : density.parent.overallMin,
40466 max : density.parent.overallMax,
40467 },
40468 yaxis: {
40469 min : density.yValMin,
40470 max : density.yValMax*1.05
40471 },
40472 hooks: {
40473 draw : drawLines
40474 },
40475 };
40476 if (!density.parent.options.showYAxis)
40477 options.yaxis.show=false;
40478
40479 var highlight_select_plot_colors = [];
40480 var i = 0;
40481 $(highlight_select_plot).each(function(){
40482 var color;
40483 if (i < GeoTemConfig.datasets.length){
40484 var datasetColors = GeoTemConfig.getColor(i);
40485 if (highlight_select_plot.length>GeoTemConfig.datasets.length)
40486 color = "rgb("+datasetColors.r0+","+datasetColors.g0+","+datasetColors.b0+")";
40487 else
40488 color = "rgb("+datasetColors.r1+","+datasetColors.g1+","+datasetColors.b1+")";
40489 } else {
40490 var datasetColors = GeoTemConfig.getColor(i-GeoTemConfig.datasets.length);
40491 color = "rgb("+datasetColors.r1+","+datasetColors.g1+","+datasetColors.b1+")";
40492 }
40493
40494 highlight_select_plot_colors.push({
40495 color : color,
40496 data : this
40497 });
40498 i++;
40499 });
40500
40501 density.plot = $.plot($(density.div), highlight_select_plot_colors, options);
40502 density.parent.drawHandles();
40503
40504 var rangeBars = density.parent.rangeBars;
40505 if (typeof rangeBars !== "undefined")
40506 $(density.div).unbind("plothover", rangeBars.hoverFunction);
40507 $(density.div).unbind("plothover", density.hoverFunction);
40508 $(density.div).bind("plothover", density.hoverFunction);
40509
40510 //this var prevents the execution of the plotclick event after a select event
40511 density.wasSelection = false;
40512 $(density.div).unbind("plotclick");
40513 $(density.div).bind("plotclick", density.clickFunction);
40514
40515 $(density.div).unbind("plotselected");
40516 $(density.div).bind("plotselected", density.selectFuntion);
40517 },
40518
40519 hoverFunction : function (event, pos, item) {
40520 var hoverPoint;
40521 //TODO: this could be wanted (if negative weight is used)
40522 if ((item)&&(item.datapoint[1] != 0)) {
40523 //at begin and end of plot there are added 0 points
40524 hoverPoint = item.dataIndex-1;
40525 }
40526 //remember last point, so that we don't redraw the current state
40527 //that "hoverPoint" may be undefined is on purpose
40528 if (density.highlighted !== hoverPoint){
40529 density.highlighted = hoverPoint;
40530 density.triggerHighlight(hoverPoint);
40531 }
40532 },
40533
40534 clickFunction : function (event, pos, item) {
40535 if (density.wasSelection)
40536 density.wasSelection = false;
40537 else {
40538 //remove selection handles (if there were any)
40539 density.parent.clearHandles();
40540
40541 var selectPoint;
40542 //that date may be undefined is on purpose
40543 //TODO: ==0 could be wanted (if negative weight is used)
40544 if ((item)&&(item.datapoint[1] != 0)) {
40545 //at begin and end of plot there are added 0 points
40546 selectPoint = item.dataIndex-1;
40547 }
40548 density.triggerSelection(selectPoint);
40549 }
40550 },
40551
40552 selectFuntion : function(event, ranges) {
40553 var spanArray = density.parent.getSpanArray(density.singleTickWidth);
40554 var startSpan, endSpan;
40555 for (var i = 0; i < spanArray.length-1; i++){
40556 if ((typeof startSpan === "undefined") && (ranges.xaxis.from <= spanArray[i+1]))
40557 startSpan = i;
40558 if ((typeof endSpan === "undefined") && (ranges.xaxis.to <= spanArray[i+1]))
40559 endSpan = i;
40560 }
40561
40562 if ((typeof startSpan !== "undefined") && (typeof endSpan !== "undefined")){
40563 density.triggerSelection(startSpan, endSpan);
40564 density.wasSelection = true;
40565
40566 density.parent.clearHandles();
40567 var xaxis = density.plot.getAxes().xaxis;
40568 var x1 = density.plot.pointOffset({x:ranges.xaxis.from,y:0}).left;
40569 var x2 = density.plot.pointOffset({x:ranges.xaxis.to,y:0}).left;
40570
40571 density.parent.addHandle(x1,x2);
40572 }
40573 },
40574
40575 selectByX : function(x1, x2){
40576 density = this;
40577 var xaxis = density.plot.getAxes().xaxis;
40578 var offset = density.plot.getPlotOffset().left;
40579 var from = xaxis.c2p(x1-offset);
40580 var to = xaxis.c2p(x2-offset);
40581
40582 var spanArray = density.parent.getSpanArray(density.singleTickWidth);
40583 var startSpan, endSpan;
40584 for (var i = 0; i < spanArray.length-1; i++){
40585 if ((typeof startSpan === "undefined") && (from <= spanArray[i+1]))
40586 startSpan = i;
40587 if ((typeof endSpan === "undefined") && (to <= spanArray[i+1]))
40588 endSpan = i;
40589 }
40590
40591 if ((typeof startSpan !== "undefined") && (typeof endSpan !== "undefined")){
40592 density.triggerSelection(startSpan, endSpan);
40593 }
40594 },
40595
40596 drawDensityPlot : function(datasets, tickWidth) {
40597 var density = this;
40598 //calculate tick width (will be in ms)
40599 delete density.tickCount;
40600 delete density.singleTickWidth;
40601 delete density.highlightedDatasetsPlot;
40602 density.parent.zoomPlot(1);
40603 if (typeof tickWidth !== "undefined"){
40604 density.singleTickWidth = tickWidth;
40605 density.tickCount = Math.ceil((density.parent.overallMax-density.parent.overallMin)/tickWidth);
40606 }
40607 if ((typeof density.tickCount === "undefined") || (density.tickCount > density.maxTickCount)){
40608 density.tickCount = density.maxTickCount;
40609 density.singleTickWidth = (density.parent.overallMax-density.parent.overallMin)/density.tickCount;
40610 if (density.singleTickWidth === 0)
40611 density.singleTickWidth = 1;
40612 }
40613
40614 var hashAndPlot = density.createUDData(datasets);
40615
40616 density.datasetsPlot = hashAndPlot.plots;
40617 density.datasetsHash = hashAndPlot.hashs;
40618
40619 density.yValMin = 0;
40620 density.yValMax = 0;
40621
40622 density.combinedDatasetsPlot = [];
40623 for (var i = 0; i < density.datasetsPlot.length; i++){
40624 for (var j = 0; j < density.datasetsPlot[i].length; j++){
40625 var val = density.datasetsPlot[i][j][1];
40626
40627 if (val < density.yValMin)
40628 density.yValMin = val;
40629 if (val > density.yValMax)
40630 density.yValMax = val;
40631 }
40632 }
40633
40634 density.showPlot();
40635 },
40636
40637 triggerHighlight : function(hoverPoint) {
40638 var density = this;
40639 var highlightedObjects = [];
40640
40641
40642 if (typeof hoverPoint !== "undefined") {
40643 $(density.datasetsHash).each(function(){
40644 if (typeof this[hoverPoint] !== "undefined")
40645 highlightedObjects.push(this[hoverPoint]);
40646 else
40647 highlightedObjects.push([]);
40648 });
40649 } else {
40650 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
40651 highlightedObjects.push([]);
40652 }
40653 this.parent.core.triggerHighlight(highlightedObjects);
40654 },
40655
40656 triggerSelection : function(startPoint, endPoint) {
40657 var density = this;
40658 var selection;
40659 if (typeof startPoint !== "undefined") {
40660 if (typeof endPoint === "undefined")
40661 endPoint = startPoint;
40662 density.selected = [];
40663 $(density.datasetsHash).each(function(){
40664 var objects = [];
40665 for (var i = startPoint; i <= endPoint; i++){
40666 $(this[i]).each(function(){
40667 if ($.inArray(this, objects) == -1){
40668 objects.push(this);
40669 }
40670 });
40671 }
40672 density.selected.push(objects);
40673 });
40674
40675 selection = new Selection(density.selected, density.parent);
40676 } else {
40677 //empty selection
40678 density.selected = [];
40679 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
40680 density.selected.push([]);
40681 selection = new Selection(density.selected);
40682 }
40683
40684 this.parent.selectionChanged(selection);
40685 this.parent.core.triggerSelection(selection);
40686 },
40687
40688 highlightChanged : function(objects) {
40689 if( !GeoTemConfig.highlightEvents ){
40690 return;
40691 }
40692 var density = this;
40693 var emptyHighlight = true;
40694 var selected_highlighted = objects;
40695 if (typeof density.selected !== "undefined")
40696 selected_highlighted = GeoTemConfig.mergeObjects(objects,density.selected);
40697 $(selected_highlighted).each(function(){
40698 if ((this instanceof Array) && (this.length > 0)){
40699 emptyHighlight = false;
40700 return false;
40701 }
40702 });
40703 if (emptyHighlight && (typeof density.selected === "undefined")){
40704 density.highlightedDatasetsPlot = [];
40705 } else {
40706 density.highlightedDatasetsPlot = density.createUDData(selected_highlighted).plots;
40707 }
40708 density.showPlot();
40709 },
40710
40711 selectionChanged : function(objects) {
40712 if( !GeoTemConfig.selectionEvents ){
40713 return;
40714 }
40715 var density = this;
40716 density.selected = objects;
40717 density.highlightChanged([]);
40718 },
40719
40720 deselection : function() {
40721 },
40722
40723 filtering : function() {
40724 },
40725
40726 inverseFiltering : function() {
40727 },
40728
40729 triggerRefining : function() {
40730 },
40731
40732 reset : function() {
40733 },
40734
40735 show : function() {
40736 },
40737
40738 hide : function() {
40739 }
40740 };
40741 /*
40742 * FuzzyTimelineGui.js
40743 *
40744 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
40745 *
40746 * This library is free software; you can redistribute it and/or
40747 * modify it under the terms of the GNU Lesser General Public
40748 * License as published by the Free Software Foundation; either
40749 * version 3 of the License, or (at your option) any later version.
40750 *
40751 * This library is distributed in the hope that it will be useful,
40752 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40753 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40754 * Lesser General Public License for more details.
40755 *
40756 * You should have received a copy of the GNU Lesser General Public
40757 * License along with this library; if not, write to the Free Software
40758 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
40759 * MA 02110-1301 USA
40760 */
40761
40762 /**
40763 * @class FuzzyTimelineGui
40764 * FuzzyTimeline GUI Implementation
40765 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
40766 *
40767 * @param {FuzzyTimelineWidget} parent FuzzyTimeline widget object
40768 * @param {HTML object} div parent div to append the FuzzyTimeline gui
40769 * @param {JSON} options FuzzyTimeline configuration
40770 */
40771 function FuzzyTimelineGui(fuzzyTimelineWidget, div, options) {
40772
40773 this.parent = fuzzyTimelineWidget;
40774 var fuzzyTimelineGui = this;
40775
40776 this.fuzzyTimelineContainer = div;
40777 //if no height is given, draw it in a 32/9 ratio
40778 if ($(this.fuzzyTimelineContainer).height() === 0)
40779 $(this.fuzzyTimelineContainer).height($(this.fuzzyTimelineContainer).width()*9/32);
40780 //this.fuzzyTimelineContainer.style.position = 'relative';
40781
40782 this.sliderTable = document.createElement("table");
40783 $(this.sliderTable).addClass("ddbToolbar");
40784 $(this.sliderTable).width("100%");
40785 $(this.sliderTable).height("49px");
40786 div.appendChild(this.sliderTable);
40787
40788 this.plotDIVHeight = $(this.fuzzyTimelineContainer).height()-$(this.sliderTable).height();
40789 var plotScrollContainer = $("<div></div>");
40790 plotScrollContainer.css("overflow-x","auto");
40791 plotScrollContainer.css("overflow-y","hidden");
40792 plotScrollContainer.width("100%");
40793 plotScrollContainer.height(this.plotDIVHeight);
40794 $(div).append(plotScrollContainer);
40795 this.plotDiv = document.createElement("div");
40796 $(this.plotDiv).width("100%");
40797 $(this.plotDiv).height(this.plotDIVHeight);
40798 plotScrollContainer.append(this.plotDiv);
40799 if (this.parent.options.showRangePiechart){
40800 this.rangePiechartDiv = document.createElement("div");
40801 $(this.rangePiechartDiv).css("float","right");
40802 //alter plot div width (leave space for piechart)
40803 $(this.plotDiv).width("75%");
40804 $(this.rangePiechartDiv).width("25%");
40805 $(this.rangePiechartDiv).height(plotDIVHeight);
40806 div.appendChild(this.rangePiechartDiv);
40807 }
40808 };
40809
40810 FuzzyTimelineGui.prototype = {
40811 };
40812 /*
40813 * FuzzyTimelineRangeBars.js
40814 *
40815 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
40816 *
40817 * This library is free software; you can redistribute it and/or
40818 * modify it under the terms of the GNU Lesser General Public
40819 * License as published by the Free Software Foundation; either
40820 * version 3 of the License, or (at your option) any later version.
40821 *
40822 * This library is distributed in the hope that it will be useful,
40823 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40824 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40825 * Lesser General Public License for more details.
40826 *
40827 * You should have received a copy of the GNU Lesser General Public
40828 * License along with this library; if not, write to the Free Software
40829 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
40830 * MA 02110-1301 USA
40831 */
40832
40833 /**
40834 * @class FuzzyTimelineRangeBars
40835 * Implementation for a fuzzy time-ranges barchart
40836 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
40837 *
40838 * @param {HTML object} parent div to append the FuzzyTimeline
40839 */
40840 function FuzzyTimelineRangeBars(parent) {
40841
40842 this.rangeBars = this;
40843
40844 this.parent = parent;
40845 this.options = parent.options;
40846
40847 this.datasets;
40848 //contains selected data
40849 this.selected = undefined;
40850
40851 this.datasetsPlot;
40852 this.highlightedDatasetsPlot;
40853 this.yValMin;
40854 this.yValMax;
40855 this.displayType;
40856
40857 this.plotDiv = this.parent.gui.plotDiv;
40858
40859 this.spanWidth;
40860 this.tickSpans;
40861 this.plot;
40862 }
40863
40864 FuzzyTimelineRangeBars.prototype = {
40865
40866 initialize : function(datasets) {
40867 var rangeBar = this;
40868
40869 rangeBar.datasets = datasets;
40870 rangeBar.selected = [];
40871 },
40872
40873 createPlot : function(datasets) {
40874 var rangeBar = this;
40875 var plots = [];
40876 var objectHashes = [];
40877
40878 //-1 because last span is always empty (only there to have the ending date)
40879 var tickCount = rangeBar.tickSpans.length-1;
40880
40881 $(datasets).each(function(){
40882 var chartDataCounter = [];
40883 var objectHash = new Object();
40884
40885 for (var i = 0; i < tickCount; i++){
40886 chartDataCounter[i]=0;
40887 }
40888 //check if we got "real" datasets, or just array of objects
40889 var datasetObjects = this;
40890 if (typeof this.objects !== "undefined")
40891 datasetObjects = this.objects;
40892 $(datasetObjects).each(function(){
40893 var ticks = rangeBar.parent.getTicks(this, rangeBar.spanWidth);
40894 if (typeof ticks !== "undefined"){
40895 var exactTickCount =
40896 ticks.firstTickPercentage+
40897 ticks.lastTickPercentage+
40898 (ticks.lastTick-ticks.firstTick-1);
40899 for (var i = ticks.firstTick; i <= ticks.lastTick; i++){
40900 var weight = 0;
40901 //calculate the weight for each span, that the object overlaps
40902 if (rangeBar.parent.options.timelineMode == 'fuzzy'){
40903 //in fuzzy mode, each span gets just a fraction of the complete weight
40904 if (i == ticks.firstTick)
40905 weight = this.weight * ticks.firstTickPercentage/exactTickCount;
40906 else if (i == ticks.lastTick)
40907 weight = this.weight * ticks.lastTickPercentage/exactTickCount;
40908 else
40909 weight = this.weight * 1/exactTickCount;
40910 } else if (rangeBar.parent.options.timelineMode == 'stacking'){
40911 //in stacking mode each span gets the same amount.
40912 //(besides first and last..)
40913 if (i == ticks.firstTick)
40914 weight = this.weight * ticks.firstTickPercentage;
40915 else if (i == ticks.lastTick)
40916 weight = this.weight * ticks.lastTickPercentage;
40917 else
40918 weight = this.weight;
40919 }
40920
40921 chartDataCounter[i] += weight;
40922 //add this object to the hash
40923 if (typeof objectHash[i] === "undefined")
40924 objectHash[i] = [];
40925 objectHash[i].push(this);
40926 }
40927 }
40928 });
40929
40930 //scale according to selected type
40931 chartDataCounter = rangeBar.parent.scaleData(chartDataCounter);
40932
40933 //transform data so it can be passed to the flot barchart
40934 var plotData = [];
40935 for (var i = 0; i < tickCount; i++){
40936 plotData[i] = [];
40937 plotData[i][0] = i;
40938 plotData[i][1] = chartDataCounter[i];
40939 }
40940
40941 //delete bars with 0 values
40942 for (var i = 0; i < tickCount; i++){
40943 if (plotData[i][1]==0)
40944 delete plotData[i];
40945 }
40946
40947 plots.push(plotData);
40948 objectHashes.push(objectHash);
40949 });
40950
40951 return {plots:plots, hashs:objectHashes};
40952 },
40953
40954 showPlot : function(){
40955 var rangeBar = this;
40956 var plot = rangeBar.datasetsPlot;
40957 var highlight_select_plot = $.merge([],plot);
40958
40959 //see if there are selected/highlighted values
40960 if (rangeBar.highlightedDatasetsPlot instanceof Array){
40961 //check if plot is some other - external - graph
40962 if (plot === rangeBar.datasetsPlot)
40963 highlight_select_plot = $.merge(highlight_select_plot,rangeBar.highlightedDatasetsPlot);
40964 }
40965
40966 var tickCount = rangeBar.tickSpans.length-1;
40967 var ticks = [];
40968
40969 var axisFormatString = "YYYY";
40970 if (rangeBar.spanWidth<60*1000){
40971 axisFormatString = "YYYY/MM/DD HH:mm:ss";
40972 } else if (rangeBar.spanWidth<60*60*1000) {
40973 axisFormatString = "YYYY/MM/DD HH:mm";
40974 } else if (rangeBar.spanWidth<24*60*60*1000){
40975 axisFormatString = "YYYY/MM/DD HH";
40976 } else if (rangeBar.spanWidth<31*24*60*60*1000){
40977 axisFormatString = "YYYY/MM/DD";
40978 } else if (rangeBar.spanWidth<12*31*24*60*60*1000){
40979 axisFormatString = "YYYY/MM";
40980 }
40981 //only show ~10 labels on the x-Axis (increase if zoomed)
40982 var labelModulo = Math.ceil(tickCount/(10*rangeBar.parent.zoomFactor));
40983 for (var i = 0; i < tickCount; i++){
40984 var tickLabel = "";
40985 if (i%labelModulo==0){
40986 tickLabel = rangeBar.tickSpans[i].format(axisFormatString);
40987 }
40988 while ((tickLabel.length > 1) && (tickLabel.indexOf("0")==0))
40989 tickLabel = tickLabel.substring(1);
40990 ticks[i] = [i,tickLabel];
40991 }
40992
40993 var options = {
40994 series:{
40995 bars:{show: true}
40996 },
40997 grid: {
40998 hoverable: true,
40999 clickable: true,
41000 backgroundColor: rangeBar.parent.options.backgroundColor,
41001 borderWidth: 0,
41002 minBorderMargin: 0,
41003 },
41004 xaxis: {
41005 ticks: ticks,
41006 min : 0,
41007 max : tickCount,
41008 },
41009 yaxis: {
41010 min : rangeBar.yValMin,
41011 max : rangeBar.yValMax*1.05
41012 },
41013 tooltip: true,
41014 tooltipOpts: {
41015 content: function(label, xval, yval, flotItem){
41016 var fromLabel = rangeBar.tickSpans[xval].format(axisFormatString);
41017 while ((fromLabel.length > 1) && (fromLabel.indexOf("0")==0))
41018 fromLabel = fromLabel.substring(1);
41019 var toLabel = rangeBar.tickSpans[xval+1].clone().subtract("ms",1).format(axisFormatString);
41020 while ((toLabel.length > 1) && (toLabel.indexOf("0")==0))
41021 toLabel = toLabel.substring(1);
41022 highlightString = fromLabel + " - " + toLabel + " : ";
41023 //(max.)2 Nachkomma-Stellen von y-Wert anzeigen
41024 highlightString += Math.round(yval*100)/100;
41025
41026 return highlightString;
41027 }
41028 },
41029 selection: {
41030 mode: "x"
41031 }
41032 };
41033 if (!rangeBar.parent.options.showYAxis)
41034 options.yaxis.show=false;
41035
41036 var highlight_select_plot_colors = [];
41037 var i = 0;
41038 $(highlight_select_plot).each(function(){
41039 var color;
41040 if (i < GeoTemConfig.datasets.length){
41041 var datasetColors = GeoTemConfig.getColor(i);
41042 if (highlight_select_plot.length>GeoTemConfig.datasets.length)
41043 color = "rgb("+datasetColors.r0+","+datasetColors.g0+","+datasetColors.b0+")";
41044 else
41045 color = "rgb("+datasetColors.r1+","+datasetColors.g1+","+datasetColors.b1+")";
41046 } else {
41047 var datasetColors = GeoTemConfig.getColor(i-GeoTemConfig.datasets.length);
41048 color = "rgb("+datasetColors.r1+","+datasetColors.g1+","+datasetColors.b1+")";
41049 }
41050
41051 highlight_select_plot_colors.push({
41052 color : color,
41053 data : this
41054 });
41055 i++;
41056 });
41057
41058 $(rangeBar.plotDiv).unbind();
41059 rangeBar.plot = $.plot($(rangeBar.plotDiv), highlight_select_plot_colors, options);
41060 rangeBar.parent.drawHandles();
41061
41062 var density = rangeBar.parent.density;
41063 if (typeof density !== "undefined")
41064 $(rangeBar.plotDiv).unbind("plothover", density.hoverFunction);
41065 $(rangeBar.plotDiv).unbind("plothover", rangeBar.hoverFunction);
41066 $(rangeBar.plotDiv).bind("plothover", $.proxy(rangeBar.hoverFunction,rangeBar));
41067
41068 //this var prevents the execution of the plotclick event after a select event
41069 rangeBar.wasSelection = false;
41070 $(rangeBar.plotDiv).unbind("plotclick");
41071 $(rangeBar.plotDiv).bind("plotclick", $.proxy(rangeBar.clickFunction,rangeBar));
41072
41073 $(rangeBar.plotDiv).unbind("plotselected");
41074 $(rangeBar.plotDiv).bind("plotselected", $.proxy(rangeBar.selectFunction,rangeBar));
41075 },
41076
41077 hoverFunction : function (event, pos, item) {
41078 var rangeBar = this;
41079 var hoverBar;
41080 var spans;
41081 if (item) {
41082 hoverBar = item.datapoint[0];
41083 }
41084 //remember last date, so that we don't redraw the current state
41085 //that date may be undefined is on purpose
41086 if (rangeBar.highlighted !== hoverBar){
41087 rangeBar.highlighted = hoverBar;
41088 if (typeof hoverBar === "undefined")
41089 rangeBar.triggerHighlight();
41090 else
41091 rangeBar.triggerHighlight(hoverBar);
41092 }
41093 },
41094
41095 clickFunction : function (event, pos, item) {
41096 var rangeBar = this;
41097 if (rangeBar.wasSelection)
41098 rangeBar.wasSelection = false;
41099 else {
41100 //remove selection handles (if there were any)
41101 rangeBar.parent.clearHandles();
41102
41103 var clickBar;
41104 if (item) {
41105 //contains the x-value (date)
41106 clickBar = item.datapoint[0];
41107 }
41108 if (typeof clickBar === "undefined")
41109 rangeBar.triggerSelection();
41110 else
41111 rangeBar.triggerSelection(clickBar);
41112 wasDataClick = true;
41113 }
41114 },
41115
41116 selectFunction : function(event, ranges) {
41117 var rangeBar = this;
41118 startBar = Math.floor(ranges.xaxis.from);
41119 endBar = Math.floor(ranges.xaxis.to);
41120 rangeBar.triggerSelection(startBar, endBar);
41121 rangeBar.wasSelection = true;
41122
41123 rangeBar.parent.clearHandles();
41124 var xaxis = rangeBar.plot.getAxes().xaxis;
41125 var x1 = rangeBar.plot.pointOffset({x:ranges.xaxis.from,y:0}).left;
41126 var x2 = rangeBar.plot.pointOffset({x:ranges.xaxis.to,y:0}).left;
41127 rangeBar.parent.addHandle(x1,x2);
41128 },
41129
41130 selectByX : function(x1, x2){
41131 rangeBar = this;
41132 var xaxis = rangeBar.plot.getAxes().xaxis;
41133 var offset = rangeBar.plot.getPlotOffset().left;
41134 var from = Math.floor(xaxis.c2p(x1-offset));
41135 var to = Math.floor(xaxis.c2p(x2-offset));
41136
41137 rangeBar.triggerSelection(from, to);
41138 },
41139
41140 drawRangeBarChart : function(datasets, spanWidth){
41141 var rangeBar = this;
41142 rangeBar.spanWidth = spanWidth;
41143 rangeBar.tickSpans = rangeBar.parent.getSpanArray(rangeBar.spanWidth);
41144 //-1 because last span is always empty (only there to have the ending date)
41145 var tickCount = rangeBar.tickSpans.length-1;
41146
41147 if (tickCount > rangeBar.options.maxBars){
41148 var zoomFactor = tickCount / rangeBar.options.maxBars;
41149 rangeBar.parent.zoomPlot(zoomFactor);
41150 } else
41151 rangeBar.parent.zoomPlot(1);
41152
41153 rangeBar.yValMin = 0;
41154 rangeBar.yValMax = 0;
41155
41156 var plotAndHash = rangeBar.createPlot(datasets);
41157 rangeBar.datasetsPlot = plotAndHash.plots;
41158 rangeBar.datasetsHash = plotAndHash.hashs;
41159 delete rangeBar.highlightedDatasetsPlot;
41160 //redraw selected plot to fit (possible) new scale
41161 rangeBar.selectionChanged(rangeBar.selected);
41162
41163 //get min and max values
41164 for (var i = 0; i < rangeBar.datasetsPlot.length; i++){
41165 for (var j = 0; j < rangeBar.datasetsPlot[i].length; j++){
41166 if (typeof rangeBar.datasetsPlot[i][j] !== "undefined"){
41167 var val = rangeBar.datasetsPlot[i][j][1];
41168
41169 if (val < rangeBar.yValMin)
41170 rangeBar.yValMin = val;
41171 if (val > rangeBar.yValMax)
41172 rangeBar.yValMax = val;
41173 }
41174 }
41175 }
41176
41177 rangeBar.showPlot();
41178 },
41179
41180 highlightChanged : function(objects) {
41181 if( !GeoTemConfig.highlightEvents ){
41182 return;
41183 }
41184 var rangeBar = this;
41185 var emptyHighlight = true;
41186 var selected_highlighted = objects;
41187 if (typeof rangeBar.selected !== "undefined")
41188 var selected_highlighted = GeoTemConfig.mergeObjects(objects,rangeBar.selected);
41189 $(selected_highlighted).each(function(){
41190 if ((this instanceof Array) && (this.length > 0)){
41191 emptyHighlight = false;
41192 return false;
41193 }
41194 });
41195 if (emptyHighlight && (typeof rangeBar.selected === "undefined")){
41196 rangeBar.highlightedDatasetsPlot = [];
41197 } else {
41198 rangeBar.highlightedDatasetsPlot = rangeBar.createPlot(selected_highlighted).plots;
41199 }
41200 rangeBar.showPlot();
41201 },
41202
41203 selectionChanged : function(objects) {
41204 if( !GeoTemConfig.selectionEvents ){
41205 return;
41206 }
41207 var rangeBar = this;
41208 rangeBar.selected = objects;
41209 rangeBar.highlightChanged([]);
41210 },
41211
41212 triggerHighlight : function(hoverPoint) {
41213 var rangeBar = this;
41214 var highlightedObjects = [];
41215
41216 if (typeof hoverPoint !== "undefined"){
41217 $(rangeBar.datasetsHash).each(function(){
41218 if (typeof this[hoverPoint] !== "undefined")
41219 highlightedObjects.push(this[hoverPoint]);
41220 else
41221 highlightedObjects.push([]);
41222 });
41223 } else {
41224 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
41225 highlightedObjects.push([]);
41226 }
41227
41228 this.parent.core.triggerHighlight(highlightedObjects);
41229 },
41230
41231 triggerSelection : function(startBar, endBar) {
41232 var rangeBar = this;
41233 var selection;
41234 if (typeof startBar !== "undefined") {
41235 if (typeof endBar === "undefined")
41236 endBar = startBar;
41237 rangeBar.selected = [];
41238 $(rangeBar.datasetsHash).each(function(){
41239 var objects = [];
41240 for (var i = startBar; i <= endBar; i++){
41241 $(this[i]).each(function(){
41242 if ($.inArray(this, objects) == -1){
41243 objects.push(this);
41244 }
41245 });
41246 }
41247 rangeBar.selected.push(objects);
41248 });
41249 selection = new Selection(rangeBar.selected, rangeBar.parent);
41250 } else {
41251 rangeBar.selected = [];
41252 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
41253 rangeBar.selected.push([]);
41254 selection = new Selection(rangeBar.selected);
41255 }
41256
41257 rangeBar.parent.selectionChanged(selection);
41258 rangeBar.parent.core.triggerSelection(selection);
41259 },
41260
41261 deselection : function() {
41262 },
41263
41264 filtering : function() {
41265 },
41266
41267 inverseFiltering : function() {
41268 },
41269
41270 triggerRefining : function() {
41271 },
41272
41273 reset : function() {
41274 },
41275
41276 show : function() {
41277 },
41278
41279 hide : function() {
41280 }
41281 };
41282 /*
41283 * FuzzyTimelineRangePiechart.js
41284 *
41285 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
41286 *
41287 * This library is free software; you can redistribute it and/or
41288 * modify it under the terms of the GNU Lesser General Public
41289 * License as published by the Free Software Foundation; either
41290 * version 3 of the License, or (at your option) any later version.
41291 *
41292 * This library is distributed in the hope that it will be useful,
41293 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41294 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41295 * Lesser General Public License for more details.
41296 *
41297 * You should have received a copy of the GNU Lesser General Public
41298 * License along with this library; if not, write to the Free Software
41299 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
41300 * MA 02110-1301 USA
41301 */
41302
41303 /**
41304 * @class FuzzyTimelineRangePiechart
41305 * Implementation for a fuzzy time-ranges pie chart
41306 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
41307 *
41308 * @param {HTML object} parent div to append the FuzzyTimeline
41309 */
41310 function FuzzyTimelineRangePiechart(parent,div) {
41311
41312 this.fuzzyTimeline = this;
41313
41314 this.parent = parent;
41315 this.options = parent.options;
41316
41317 this.div = div;
41318
41319 this.selected = [];
41320
41321 this.maxSlices = 10;
41322 }
41323
41324 FuzzyTimelineRangePiechart.prototype = {
41325
41326 initialize : function(datasets) {
41327 var piechart = this;
41328 if (piechart.parent.showRangePiechart){
41329 piechart.datasets = datasets;
41330 piechart.drawPieChart(piechart.datasets);
41331 }
41332 },
41333
41334 drawPieChart : function(datasets){
41335 var piechart = this;
41336 //build hashmap of spans (span length -> objects[])
41337 var spans = [];
41338 var index = 0;
41339 $(datasets).each(function(){
41340 var objects = this;
41341 //check whether we got "real" dataset or just a set of DataObjects
41342 if (typeof objects.objects !== "undefined")
41343 objects = objects.objects;
41344 $(objects).each(function(){
41345 var dataObject = this;
41346 var span;
41347 if (dataObject.isTemporal){
41348 span = SimileAjax.DateTime.MILLISECOND;
41349 } else if (dataObject.isFuzzyTemporal){
41350 span = dataObject.TimeSpanGranularity;
41351 }
41352
41353 if (typeof span === "undefined")
41354 return;
41355
41356 var found = false;
41357 $(spans).each(function(){
41358 if (this.span === span){
41359 this.objects[index].push(dataObject);
41360 found = true;
41361 return false;
41362 }
41363 });
41364 if (found === false){
41365 var newObjectSet = [];
41366 for (var i = 0; i < piechart.datasets.length; i++)
41367 newObjectSet.push([]);
41368 newObjectSet[index].push(dataObject);
41369 spans.push({span:span,objects:newObjectSet});
41370 }
41371 });
41372 index++;
41373 });
41374
41375 //TODO: join elements of span array to keep below certain threshold
41376
41377 //sort array by span length
41378 spans.sort(function(a,b){
41379 return(a.span-b.span);
41380 });
41381
41382 //create chart data
41383 var chartData = [];
41384 $(spans).each(function(){
41385 var spanElem = this;
41386 $(spanElem.objects).each(function(){
41387 var label = "unknown";
41388
41389 if (spanElem.span === SimileAjax.DateTime.MILLENNIUM){
41390 label = "millenia";
41391 } else if (spanElem.span === SimileAjax.DateTime.DECADE){
41392 label = "decades";
41393 } else if (spanElem.span === SimileAjax.DateTime.CENTURY){
41394 label = "centuries";
41395 } else if (spanElem.span === SimileAjax.DateTime.YEAR){
41396 label = "years";
41397 } else if (spanElem.span === SimileAjax.DateTime.MONTH){
41398 label = "months";
41399 } else if (spanElem.span === SimileAjax.DateTime.DAY){
41400 label = "days";
41401 } else if (spanElem.span === SimileAjax.DateTime.HOUR){
41402 label = "hours";
41403 } else if (spanElem.span === SimileAjax.DateTime.MINUTE){
41404 label = "minutes";
41405 } else if (spanElem.span === SimileAjax.DateTime.SECOND){
41406 label = "seconds";
41407 } else if (spanElem.span === SimileAjax.DateTime.MILLISECOND){
41408 label = "milliseconds";
41409 }
41410
41411 chartData.push({label:label,data:this.length});
41412 });
41413 });
41414
41415 $(piechart.div).unbind("plotclick");
41416 $(piechart.div).unbind("plothover");
41417 $(piechart.div).empty();
41418 if (spans.length === 0){
41419 //TODO: language specific message
41420 $(piechart.div).append("empty selection");
41421 } else {
41422 $.plot($(piechart.div), chartData,
41423 {
41424 series: {
41425 // Make this a pie chart.
41426 pie: {
41427 show:true
41428 }
41429 },
41430 legend: { show:false},
41431 grid: {
41432 hoverable: true,
41433 clickable: true
41434 },
41435 tooltip: true,
41436 }
41437 );
41438
41439 var lastHighlighted;
41440 var hoverFunction = function (event, pos, item) {
41441 if (item) {
41442 var highlightedSpan = Math.ceil(item.seriesIndex/piechart.datasets.length);
41443 if (lastHighlighted !== highlightedSpan){
41444 var highlightedObjects = [];
41445 for(;highlightedSpan>=0;highlightedSpan--){
41446 highlightedObjects = GeoTemConfig.mergeObjects(highlightedObjects,spans[highlightedSpan].objects);
41447 }
41448 lastHighlighted = highlightedSpan;
41449 }
41450 piechart.triggerHighlight(highlightedObjects);
41451 } else {
41452 piechart.triggerHighlight([]);
41453 }
41454 };
41455 $(piechart.div).bind("plothover", hoverFunction);
41456
41457 $(piechart.div).bind("plotclick", function (event, pos, item) {
41458 $(piechart.div).unbind("plothover");
41459 if (item){
41460 var selectedSpan = Math.ceil(item.seriesIndex/piechart.datasets.length);
41461 var selectedObjects = [];
41462 for(;selectedSpan>=0;selectedSpan--){
41463 selectedObjects = GeoTemConfig.mergeObjects(selectedObjects,spans[selectedSpan].objects);
41464 }
41465 piechart.triggerSelection(selectedObjects);
41466 } else {
41467 //if it was a click outside of the pie-chart, enable highlight events
41468 $(piechart.div).bind("plothover", hoverFunction);
41469 //return to old state
41470 piechart.triggerSelection(piechart.selected);
41471 //and redraw piechart
41472 piechart.highlightChanged([]);
41473 }
41474 });
41475 }
41476 },
41477
41478 highlightChanged : function(objects) {
41479 var piechart = this;
41480 if (piechart.parent.showRangePiechart){
41481 //check if this is an empty highlight
41482 var emptyHighlight = true;
41483 $(objects).each(function(){
41484 if ((this instanceof Array) && (this.length > 0)){
41485 emptyHighlight = false;
41486 return false;
41487 }
41488 });
41489
41490 if (emptyHighlight === false)
41491 piechart.drawPieChart(GeoTemConfig.mergeObjects(piechart.selected, objects));
41492 else{
41493 //return to selection (or all objects, if no selection is active)
41494 if (piechart.selected.length > 0)
41495 piechart.drawPieChart(piechart.selected);
41496 else
41497 piechart.drawPieChart(piechart.datasets);
41498 }
41499 }
41500 },
41501
41502 selectionChanged : function(selection) {
41503 var piechart = this;
41504 if (piechart.parent.showRangePiechart){
41505 if( !GeoTemConfig.selectionEvents ){
41506 return;
41507 }
41508 piechart.selected = selection;
41509 piechart.highlightChanged([]);
41510 }
41511 },
41512
41513 triggerHighlight : function(highlightedObjects) {
41514 this.parent.triggerHighlight(highlightedObjects);
41515 },
41516
41517 triggerSelection : function(selectedObjects) {
41518 this.parent.triggerSelection(selectedObjects);
41519 },
41520
41521 deselection : function() {
41522 },
41523
41524 filtering : function() {
41525 },
41526
41527 inverseFiltering : function() {
41528 },
41529
41530 triggerRefining : function() {
41531 },
41532
41533 reset : function() {
41534 },
41535
41536 show : function() {
41537 },
41538
41539 hide : function() {
41540 }
41541 };
41542 /*
41543 * FuzzyTimelineRangeSlider.js
41544 *
41545 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
41546 *
41547 * This library is free software; you can redistribute it and/or
41548 * modify it under the terms of the GNU Lesser General Public
41549 * License as published by the Free Software Foundation; either
41550 * version 3 of the License, or (at your option) any later version.
41551 *
41552 * This library is distributed in the hope that it will be useful,
41553 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41554 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41555 * Lesser General Public License for more details.
41556 *
41557 * You should have received a copy of the GNU Lesser General Public
41558 * License along with this library; if not, write to the Free Software
41559 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
41560 * MA 02110-1301 USA
41561 */
41562
41563 /**
41564 * @class FuzzyTimelineRangeSlider
41565 * Implementation for a fuzzy time-ranges slider
41566 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
41567 *
41568 * @param {HTML object} parent div to append the FuzzyTimeline
41569 */
41570 function FuzzyTimelineRangeSlider(parent) {
41571
41572 var rangeSlider = this;
41573
41574 this.parent = parent;
41575 this.options = parent.options;
41576
41577 this.spans;
41578
41579 this.datasets;
41580
41581 this.sliderParentTable = this.parent.gui.sliderTable;
41582 var headerRow = $("<tr></tr>");
41583 var controlsRow = $("<tr></tr>");
41584 $(this.sliderParentTable).append(headerRow).append(controlsRow);
41585
41586 headerRow.append("<td>Time start</td>");
41587 this.rangeStart = document.createElement("select");
41588 controlsRow.append($("<td></td>").append(this.rangeStart));
41589
41590 headerRow.append("<td>Time unit</td>");
41591 this.rangeDropdown = document.createElement("select");
41592 controlsRow.append($("<td></td>").append(this.rangeDropdown));
41593
41594 headerRow.append("<td>Scaling</td>");
41595 this.scalingDropdown = document.createElement("select");
41596 controlsRow.append($("<td></td>").append(this.scalingDropdown));
41597 $(this.scalingDropdown).append("<option>normal</option>");
41598 $(this.scalingDropdown).append("<option>logarithm</option>");
41599 $(this.scalingDropdown).append("<option>percentage</option>");
41600 $(this.scalingDropdown).change(function(eventObject){
41601 var scaleMode = $(rangeSlider.scalingDropdown).find("option:selected").text();
41602 rangeSlider.parent.changeScaleMode(scaleMode);
41603 });
41604
41605 headerRow.append("<td>Animation</td>");
41606 this.startAnimation = document.createElement("div");
41607 $(this.startAnimation).addClass("smallButton playDisabled");
41608 this.pauseAnimation = document.createElement("div");
41609 $(this.pauseAnimation).addClass("smallButton pauseDisabled");
41610 controlsRow.append($("<td></td>").append(this.startAnimation).append(this.pauseAnimation));
41611
41612 headerRow.append("<td>Dated Objects</td>");
41613 this.numberDatedObjects = 0;
41614 this.numberDatedObjectsDIV = document.createElement("div");
41615 $(this.numberDatedObjectsDIV).addClass("ddbElementsCount");
41616 controlsRow.append($("<td></td>").append(this.numberDatedObjectsDIV));
41617 }
41618
41619 FuzzyTimelineRangeSlider.prototype = {
41620
41621 initialize : function(datasets) {
41622 var rangeSlider = this;
41623 rangeSlider.datasets = datasets;
41624
41625 //reset values
41626 rangeSlider.spans = [];
41627 rangeSlider.spanHash = [];
41628
41629 //find smallest (most accurate) time-span
41630 var smallestSpan;
41631 rangeSlider.numberDatedObjects = 0;
41632 $(this.datasets).each(function(){
41633 $(this.objects).each(function(){
41634 var dataObject = this;
41635 var span;
41636 if (dataObject.isTemporal){
41637 rangeSlider.numberDatedObjects++;
41638 smallestSpan = moment.duration(1,'milliseconds');
41639 } else if (dataObject.isFuzzyTemporal){
41640 rangeSlider.numberDatedObjects++;
41641 span = moment.duration(dataObject.TimeSpanEnd-dataObject.TimeSpanBegin);
41642 if ( (typeof smallestSpan === 'undefined') || (span < smallestSpan))
41643 smallestSpan = span;
41644 }
41645 });
41646 if ((typeof smallestSpan !== 'undefined') && (smallestSpan.asMilliseconds() === 1))
41647 return false;
41648 });
41649
41650 //show number of objects that have a time in header
41651 $(rangeSlider.numberDatedObjectsDIV).empty().append(rangeSlider.numberDatedObjects + " results");
41652
41653 if (typeof smallestSpan === 'undefined')
41654 return;
41655
41656 var fixedSpans = [
41657 moment.duration(1, 'seconds'),
41658 moment.duration(1, 'minutes'),
41659 moment.duration(10, 'minutes'),
41660 moment.duration(15, 'minutes'),
41661 moment.duration(30, 'minutes'),
41662 moment.duration(1, 'hours'),
41663 moment.duration(5, 'hours'),
41664 moment.duration(10, 'hours'),
41665 moment.duration(12, 'hours'),
41666 moment.duration(1, 'days'),
41667 moment.duration(7, 'days'),
41668 moment.duration(1, 'weeks'),
41669 moment.duration(2, 'weeks'),
41670 moment.duration(1, 'months'),
41671 moment.duration(2, 'months'),
41672 moment.duration(3, 'months'),
41673 moment.duration(6, 'months'),
41674 moment.duration(1, 'years'),
41675 moment.duration(5, 'years'),
41676 moment.duration(10, 'years'),
41677 moment.duration(20, 'years'),
41678 moment.duration(25, 'years'),
41679 moment.duration(50, 'years'),
41680 moment.duration(100, 'years'),
41681 moment.duration(200, 'years'),
41682 moment.duration(250, 'years'),
41683 moment.duration(500, 'years'),
41684 moment.duration(1000, 'years'),
41685 moment.duration(2000, 'years'),
41686 moment.duration(2500, 'years'),
41687 moment.duration(5000, 'years'),
41688 moment.duration(10000, 'years'),
41689 ];
41690 var overallSpan = rangeSlider.parent.overallMax-rangeSlider.parent.overallMin;
41691 //only add spans that are not too small for the data
41692 for (var i = 0; i < fixedSpans.length; i++){
41693 if ( (fixedSpans[i].asMilliseconds() > (smallestSpan.asMilliseconds() * 0.25)) &&
41694 (fixedSpans[i].asMilliseconds() < overallSpan)
41695 &&
41696 (
41697 rangeSlider.parent.options.showAllPossibleSpans ||
41698 ((rangeSlider.parent.overallMax-rangeSlider.parent.overallMin)/fixedSpans[i]<rangeSlider.options.maxBars)
41699 ))
41700 rangeSlider.spans.push(fixedSpans[i]);
41701 }
41702
41703 $(rangeSlider.rangeDropdown).empty();
41704
41705 $(rangeSlider.rangeDropdown).append("<option>continuous</option>");
41706 var index = 0;
41707 $(rangeSlider.spans).each(function(){
41708 var duration = this;
41709 if (duration < moment.duration(1,'second'))
41710 humanizedSpan = duration.milliseconds() + "ms";
41711 else if (duration < moment.duration(1,'minute'))
41712 humanizedSpan = duration.seconds() + "s";
41713 else if (duration < moment.duration(1,'hour'))
41714 humanizedSpan = duration.minutes() + "min";
41715 else if (duration < moment.duration(1,'day'))
41716 humanizedSpan = duration.hours() + "h";
41717 else if (duration < moment.duration(1,'month')){
41718 var days = duration.days();
41719 humanizedSpan = days + " day";
41720 if (days > 1)
41721 humanizedSpan += "s";
41722 } else if (duration < moment.duration(1,'year')){
41723 var months = duration.months();
41724 humanizedSpan = months + " month";
41725 if (months > 1)
41726 humanizedSpan += "s";
41727 } else {
41728 var years = duration.years();
41729 humanizedSpan = years + " year";
41730 if (years > 1)
41731 humanizedSpan += "s";
41732 }
41733 $(rangeSlider.rangeDropdown).append("<option index='"+index+"'>"+humanizedSpan+"</option>");
41734 index++;
41735 });
41736
41737 $(rangeSlider.rangeDropdown).change(function( eventObject ){
41738 var handlePosition = $(rangeSlider.rangeDropdown).find("option:selected").first().attr("index");
41739 //if there is no index, "continuous" is selected - so the density plot will be drawn
41740
41741 if (typeof handlePosition === "undefined"){
41742 rangeSlider.parent.switchViewMode("density");
41743 } else {
41744 rangeSlider.parent.switchViewMode("barchart");
41745 }
41746
41747 rangeSlider.parent.slidePositionChanged(rangeSlider.spans[handlePosition]);
41748 });
41749
41750 $(rangeSlider.rangeStart).empty();
41751 //add start of timeline selections
41752 //TODO: add Months/Days/etc., atm there are only years
41753 var starts = [];
41754 var overallMin = rangeSlider.parent.overallMin;
41755 var last = moment(overallMin).year();
41756 starts.push(last);
41757 for (i = 1;;i++){
41758 var date = moment(overallMin).year();
41759 date = date/Math.pow(10,i);
41760 if (Math.abs(date)<1)
41761 break;
41762 date = Math.floor(date);
41763 date = date*Math.pow(10,i);
41764 if (date != last)
41765 starts.push(date);
41766 last = date;
41767 }
41768 $(starts).each(function(){
41769 $(rangeSlider.rangeStart).append("<option>"+this+"</option>");
41770 });
41771
41772 $(rangeSlider.rangeStart).change(function( eventObject ){
41773 var handlePosition = rangeSlider.rangeStart.selectedIndex;
41774 var start = starts[handlePosition];
41775
41776 rangeSlider.parent.overallMin = moment().year(start);
41777 $(rangeSlider.rangeDropdown).change();
41778 });
41779
41780 $(rangeSlider.rangeDropdown).change();
41781
41782 $(rangeSlider.startAnimation).click(function(){
41783 if ($(rangeSlider.startAnimation).hasClass("playEnabled")){
41784 $(rangeSlider.startAnimation).removeClass("playEnabled").addClass("playDisabled");
41785 $(rangeSlider.pauseAnimation).removeClass("pauseDisabled").addClass("pauseEnabled");
41786
41787 rangeSlider.parent.startAnimation();
41788 }
41789 });
41790
41791 $(rangeSlider.pauseAnimation).prop('disabled', true);
41792 $(rangeSlider.pauseAnimation).click(function(){
41793 if ($(rangeSlider.pauseAnimation).hasClass("pauseEnabled")){
41794 $(rangeSlider.startAnimation).removeClass("playDisabled").addClass("playEnabled");
41795 $(rangeSlider.pauseAnimation).removeClass("pauseEnabled").addClass("pauseDisabled");
41796
41797 rangeSlider.parent.pauseAnimation();
41798 }
41799 });
41800 },
41801
41802 triggerHighlight : function(columnElement) {
41803
41804 },
41805
41806 triggerSelection : function(columnElement) {
41807
41808 },
41809
41810 deselection : function() {
41811 },
41812
41813 filtering : function() {
41814 },
41815
41816 inverseFiltering : function() {
41817 },
41818
41819 triggerRefining : function() {
41820 },
41821
41822 reset : function() {
41823 },
41824
41825 show : function() {
41826 },
41827
41828 hide : function() {
41829 }
41830 };
41831 /*
41832 * FuzzyTimelineWidget.js
41833 *
41834 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
41835 *
41836 * This library is free software; you can redistribute it and/or
41837 * modify it under the terms of the GNU Lesser General Public
41838 * License as published by the Free Software Foundation; either
41839 * version 3 of the License, or (at your option) any later version.
41840 *
41841 * This library is distributed in the hope that it will be useful,
41842 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41843 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41844 * Lesser General Public License for more details.
41845 *
41846 * You should have received a copy of the GNU Lesser General Public
41847 * License along with this library; if not, write to the Free Software
41848 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
41849 * MA 02110-1301 USA
41850 */
41851
41852 /**
41853 * @class FuzzyTimelineWidget
41854 * FuzzyTimelineWidget Implementation
41855 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
41856 *
41857 * @param {WidgetWrapper} core wrapper for interaction to other widgets
41858 * @param {HTML object} div parent div to append the FuzzyTimeline widget div
41859 * @param {JSON} options user specified configuration that overwrites options in FuzzyTimelineConfig.js
41860 */
41861 FuzzyTimelineWidget = function(core, div, options) {
41862
41863 this.datasets;
41864 this.selected = undefined;
41865 this.overallMin;
41866 this.overallMax;
41867
41868 this.core = core;
41869 this.core.setWidget(this);
41870
41871 this.options = (new FuzzyTimelineConfig(options)).options;
41872 this.gui = new FuzzyTimelineGui(this, div, this.options);
41873
41874 this.viewMode;
41875 this.density;
41876 this.rangeSlider;
41877 this.rangeBars;
41878 this.rangePiechart;
41879 this.spanHash = [];
41880
41881 this.handles = [];
41882 this.zoomFactor = 1;
41883
41884 this.scaleMode = "normal";
41885 }
41886
41887 FuzzyTimelineWidget.prototype = {
41888
41889 initWidget : function(data) {
41890 var fuzzyTimeline = this;
41891
41892 delete fuzzyTimeline.overallMin;
41893 delete fuzzyTimeline.overallMax;
41894
41895 $(fuzzyTimeline.gui.plotDiv).empty();
41896 $(fuzzyTimeline.gui.sliderTable).empty();
41897 delete fuzzyTimeline.rangeSlider;
41898 $(fuzzyTimeline.gui.rangePiechartDiv).empty();
41899 delete fuzzyTimeline.rangePiechart;
41900
41901 fuzzyTimeline.switchViewMode("density");
41902
41903 if ( (data instanceof Array) && (data.length > 0) )
41904 {
41905 fuzzyTimeline.datasets = data;
41906
41907 $(fuzzyTimeline.datasets).each(function(){
41908 $(this.objects).each(function(){
41909 var datemin,datemax;
41910 if (this.isTemporal){
41911 //TODO: allow more than one date
41912 datemin = moment(this.dates[0].date);
41913 datemax = datemin;
41914 } else if (this.isFuzzyTemporal){
41915 //TODO: allow more than one date
41916 datemin = this.TimeSpanBegin;
41917 datemax = this.TimeSpanEnd;
41918 }
41919
41920 if (typeof fuzzyTimeline.overallMin === "undefined")
41921 fuzzyTimeline.overallMin = datemin;
41922 if (typeof fuzzyTimeline.overallMax === "undefined")
41923 fuzzyTimeline.overallMax = datemax;
41924
41925 if (fuzzyTimeline.overallMin > datemin)
41926 fuzzyTimeline.overallMin = datemin;
41927 if (fuzzyTimeline.overallMax < datemax)
41928 fuzzyTimeline.overallMax = datemax;
41929 });
41930 });
41931
41932 fuzzyTimeline.rangeSlider = new FuzzyTimelineRangeSlider(fuzzyTimeline);
41933 fuzzyTimeline.rangeSlider.initialize(fuzzyTimeline.datasets);
41934
41935 fuzzyTimeline.rangePiechart = new FuzzyTimelineRangePiechart(fuzzyTimeline, fuzzyTimeline.gui.rangePiechartDiv);
41936 fuzzyTimeline.rangePiechart.initialize(fuzzyTimeline.datasets);
41937 }
41938 },
41939
41940 switchViewMode : function(viewMode){
41941 var fuzzyTimeline = this;
41942 if (viewMode !== fuzzyTimeline.viewMode){
41943 $(fuzzyTimeline.gui.plotDiv).empty();
41944 if (viewMode === "density"){
41945 fuzzyTimeline.density = new FuzzyTimelineDensity(fuzzyTimeline,fuzzyTimeline.gui.plotDiv);
41946 } else if (viewMode === "barchart"){
41947 fuzzyTimeline.rangeBars = new FuzzyTimelineRangeBars(fuzzyTimeline);
41948 }
41949 fuzzyTimeline.viewMode = viewMode;
41950 }
41951 },
41952
41953 scaleData : function(data){
41954 var fuzzyTimeline = this;
41955 if (fuzzyTimeline.scaleMode == "normal"){
41956 return data;
41957 } else if (fuzzyTimeline.scaleMode == "logarithm"){
41958 for(var index in data){
41959 var val = data[index];
41960 if (val!=0){
41961 var sign = 1;
41962 if (val<0){
41963 sign = -1;
41964 }
41965 data[index] = sign*Math.log(Math.abs(data[index])+1);
41966 }
41967 }
41968 return data;
41969 } else if (fuzzyTimeline.scaleMode == "percentage"){
41970 var overallCnt = 0;
41971 for(var index in data){
41972 var val = data[index];
41973 if (val > 0){
41974 overallCnt += val;
41975 }
41976 }
41977 //make 1 = 100%
41978 overallCnt = overallCnt/100;
41979 if (overallCnt != 0){
41980 for(var index in data){
41981 data[index] = (data[index])/overallCnt;
41982 }
41983 }
41984 return data;
41985 }
41986 },
41987
41988 changeScaleMode : function(scaleMode) {
41989 var fuzzyTimeline = this;
41990 fuzzyTimeline.scaleMode = scaleMode;
41991 fuzzyTimeline.drawFuzzyTimeline();
41992 },
41993
41994 slidePositionChanged : function(spanWidth) {
41995 var fuzzyTimeline = this;
41996 fuzzyTimeline.spanWidth = spanWidth;
41997 fuzzyTimeline.drawFuzzyTimeline();
41998 },
41999
42000 drawFuzzyTimeline : function(){
42001 var fuzzyTimeline = this;
42002 var datasets = fuzzyTimeline.datasets;
42003 if (fuzzyTimeline.viewMode === "density"){
42004 //redraw density plot
42005 fuzzyTimeline.density.drawDensityPlot(datasets);
42006 //select currently selected data (if there is any)
42007 fuzzyTimeline.density.selectionChanged(fuzzyTimeline.selected);
42008 } else if (fuzzyTimeline.viewMode === "barchart"){
42009 //redraw range plot
42010 fuzzyTimeline.rangeBars.drawRangeBarChart(datasets,fuzzyTimeline.spanWidth);
42011 //select currently selected data (if there is any)
42012 fuzzyTimeline.rangeBars.selectionChanged(fuzzyTimeline.selected);
42013 }
42014 },
42015
42016 highlightChanged : function(objects) {
42017 var fuzzyTimeline = this;
42018 if( !GeoTemConfig.highlightEvents ){
42019 return;
42020 }
42021 if ( (typeof objects === "undefined") || (objects.length == 0) ){
42022 return;
42023 }
42024 if (fuzzyTimeline.viewMode === "density")
42025 this.density.highlightChanged(objects);
42026 else if (fuzzyTimeline.viewMode === "barchart")
42027 this.rangeBars.highlightChanged(objects);
42028
42029 fuzzyTimeline.rangePiechart.highlightChanged(objects);
42030 },
42031
42032 selectionChanged : function(selection) {
42033 var fuzzyTimeline = this;
42034 if( !GeoTemConfig.selectionEvents ){
42035 return;
42036 }
42037 if ((typeof selection.objects !== "undefined")&&
42038 (selection.objects.length == GeoTemConfig.datasets.length)){
42039 var objectCount = 0;
42040 for (var i=0, il=selection.objects.length; i < il; i++){
42041 objectCount += selection.objects[i].length;
42042 }
42043 if (objectCount > 0){
42044 fuzzyTimeline.selected = selection.objects;
42045 } else {
42046 delete fuzzyTimeline.selected;
42047 }
42048 } else
42049 delete fuzzyTimeline.selected;
42050 if (fuzzyTimeline.viewMode === "density")
42051 this.density.selectionChanged(fuzzyTimeline.selected);
42052 else if (fuzzyTimeline.viewMode === "barchart")
42053 this.rangeBars.selectionChanged(fuzzyTimeline.selected);
42054
42055 if (selection.valid())
42056 fuzzyTimeline.rangePiechart.selectionChanged(fuzzyTimeline.selected);
42057 else
42058 fuzzyTimeline.rangePiechart.selectionChanged([]);
42059
42060 //selections "overwrite" each other
42061 if (selection.widget != fuzzyTimeline)
42062 fuzzyTimeline.clearHandles();
42063 },
42064
42065 buildSpanArray : function(spanWidth) {
42066 var spanArray = [];
42067 var tickStart = moment(this.overallMin);
42068 do{
42069 spanArray.push(moment(tickStart));
42070 tickStart.add(spanWidth);
42071 } while (tickStart <= this.overallMax);
42072 spanArray.push(moment(tickStart));
42073
42074 this.spanHash.push({spanWidth:spanWidth,overallMin:moment(this.overallMin),spanArray:spanArray});
42075 return(spanArray);
42076 },
42077
42078 getSpanArray : function(spanWidth){
42079 for (var i = 0; i < this.spanHash.length; i++){
42080 var element = this.spanHash[i];
42081 if ( ((this.overallMin-element.overallMin)===0) &&
42082 ((spanWidth-element.spanWidth)===0))
42083 return element.spanArray;
42084 }
42085 return this.buildSpanArray(spanWidth);
42086 },
42087
42088 clearSpanArray : function(){
42089 this.spanHash = [];
42090 },
42091
42092 getTicks : function(dataObject, spanWidth) {
42093 var datemin,datemax;
42094 if (dataObject.isTemporal){
42095 datemin = moment(dataObject.dates[0].date);
42096 datemax = datemin;
42097 } else if (dataObject.isFuzzyTemporal){
42098 datemin = dataObject.TimeSpanBegin;
42099 datemax = dataObject.TimeSpanEnd;
42100 } else{
42101 return;
42102 }
42103
42104 if (typeof spanWidth._data === "undefined"){
42105 //This does only work with millisecond spans, as the length of years is (very) inaccurate.
42106 //(e.g. 100-0 = 99, 2000-1000 = 1001, 5000-0 = 5003, and so on and even more: duration(5000a) = 4932a)
42107 //So the time consuming loop below is needed for accurate dates, when years/months/days etc. are supplied
42108 var firstTick = Math.floor((datemin-this.overallMin)/spanWidth);
42109 var lastTick = Math.floor((datemax-this.overallMin)/spanWidth);
42110 //calculate how much the first (and last) tick and the time-span overlap
42111 var firstTickPercentage = 1;
42112 var lastTickPercentage = 1;
42113 if (firstTick != lastTick){
42114 var secondTickStart = this.overallMin+(firstTick+1)*spanWidth;
42115 var lastTickStart = this.overallMin+lastTick*spanWidth;
42116 firstTickPercentage = (secondTickStart-datemin)/spanWidth;
42117 lastTickPercentage = (datemax-lastTickStart)/spanWidth;
42118 }
42119 if (firstTickPercentage === 0){
42120 firstTick++;
42121 firstTickPercentage = 1;
42122 }
42123 if (lastTickPercentage === 0){
42124 lastTick--;
42125 lastTickPercentage = 1;
42126 }
42127 } else {
42128 var spanArray = this.getSpanArray(spanWidth);
42129 var firstTick, lastTick;
42130 var tickCount = 0;
42131 var tickStart = spanArray[0];
42132 var lastTickStart;
42133 do{
42134 lastTickStart = spanArray[tickCount];
42135 tickCount++;
42136 tickStart = spanArray[tickCount];
42137 if ( (typeof firstTick === "undefined") && (datemin < tickStart) ){
42138 firstTick = tickCount-1;
42139 firstTickPercentage = (tickStart - datemin)/spanWidth;
42140 }
42141 if ( (typeof lastTick === "undefined") && (datemax <= tickStart) ){
42142 lastTick = tickCount-1;
42143 lastTickPercentage = (datemax - lastTickStart)/spanWidth;
42144 }
42145 } while (tickStart < datemax);
42146 if (firstTick == lastTick){
42147 firstTickPercentage = 1;
42148 lastTickPercentage = 1;
42149 }
42150 }
42151
42152 return({ firstTick:firstTick,
42153 lastTick:lastTick,
42154 firstTickPercentage:firstTickPercentage,
42155 lastTickPercentage:lastTickPercentage});
42156 },
42157
42158 getObjects : function(dateStart, dateEnd) {
42159 var fuzzyTimeline = this;
42160 var searchDateStart, searchDateEnd;
42161 if (typeof dateStart !== "undefined")
42162 searchDateStart = moment(dateStart);
42163 if (typeof dateEnd !== "undefined")
42164 searchDateEnd = moment(dateEnd);
42165
42166 var datasets = [];
42167 $(fuzzyTimeline.datasets).each(function(){
42168 var objects = [];
42169 //check if we got "real" datasets, or just array of objects
42170 var datasetObjects = this;
42171 if (typeof this.objects !== "undefined")
42172 datasetObjects = this.objects;
42173 $(datasetObjects).each(function(){
42174 var datemin,datemax;
42175 var dataObject = this;
42176 if (dataObject.isTemporal){
42177 datemin = moment(dataObject.dates[0].date);
42178 datemax = datemin;
42179 } else if (dataObject.isFuzzyTemporal){
42180 datemin = dataObject.TimeSpanBegin;
42181 datemax = dataObject.TimeSpanEnd;
42182 } else{
42183 return;
42184 }
42185
42186 if (typeof searchDateEnd === 'undefined'){
42187 if ( (datemin <= searchDateStart) && (datemax >= searchDateStart) )
42188 objects.push(this);
42189 } else {
42190 if ((datemin < searchDateEnd) && (datemax >= searchDateStart))
42191 objects.push(this);
42192 }
42193 });
42194 datasets.push(objects);
42195 });
42196
42197 return(datasets);
42198 },
42199
42200 triggerHighlight : function(highlightedObjects){
42201 var fuzzyTimeline = this;
42202 if (fuzzyTimeline.viewMode === "density")
42203 fuzzyTimeline.density.highlightChanged(highlightedObjects);
42204 else if (fuzzyTimeline.viewMode === "barchart")
42205 fuzzyTimeline.rangeBars.highlightChanged(highlightedObjects);
42206
42207 fuzzyTimeline.core.triggerHighlight(highlightedObjects);
42208 },
42209
42210 triggerSelection : function(selectedObjects){
42211 var fuzzyTimeline = this;
42212 fuzzyTimeline.selected = selectedObjects;
42213 if (fuzzyTimeline.viewMode === "density")
42214 fuzzyTimeline.density.selectionChanged(selectedObjects);
42215 else if (fuzzyTimeline.viewMode === "barchart")
42216 fuzzyTimeline.rangeBars.selectionChanged(selectedObjects);
42217
42218 selection = new Selection(selectedObjects);
42219
42220 fuzzyTimeline.core.triggerSelection(selection);
42221 },
42222
42223 addHandle : function(x1,x2){
42224 var fuzzyTimeline = this;
42225 //make sure the interval is ordered correctly
42226 if (x2<x1){
42227 var temp = x1;
42228 x1 = x2;
42229 x2 = temp;
42230 }
42231 fuzzyTimeline.handles.push({x1:x1,x2:x2});
42232 fuzzyTimeline.drawHandles();
42233 //enabled "play" button
42234 $(fuzzyTimeline.rangeSlider.startAnimation).removeClass("playDisabled").addClass("playEnabled");
42235 },
42236
42237 selectByX : function(x1,x2){
42238 var fuzzyTimeline = this;
42239 if (fuzzyTimeline.viewMode === "density"){
42240 fuzzyTimeline.density.selectByX(x1,x2);
42241 } else if (fuzzyTimeline.viewMode === "barchart"){
42242 fuzzyTimeline.rangeBars.selectByX(x1,x2);
42243 }
42244 },
42245
42246 drawHandles : function(){
42247 var fuzzyTimeline = this;
42248
42249 $(fuzzyTimeline.gui.plotDiv).find(".plotHandle").remove();
42250 $(fuzzyTimeline.gui.plotDiv).find(".dragTimeRangeAlt").remove();
42251 $(fuzzyTimeline.gui.plotDiv).find(".plotHandleBox").remove();
42252
42253 var plotHeight = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).height();
42254 var plotWidth = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).width();
42255 //flot sends the wrong width if we extend the parent div, so scale it accordingly
42256 plotWidth = plotWidth*fuzzyTimeline.zoomFactor;
42257 var plotOffset = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).getPlotOffset().left;
42258
42259 $(fuzzyTimeline.handles).each(function(){
42260 var handle = this;
42261
42262 var moveLeftHandle = function(){
42263 leftHandle.style.left = handle.x1-$(leftHandle).width() + "px";
42264 };
42265
42266 var moveRightHandle = function(){
42267 rightHandle.style.left = handle.x2+ "px";
42268 };
42269
42270 var resizeHandleBox = function(){
42271 handleBox.style.left = handle.x1+"px";
42272 $(handleBox).width(handle.x2-handle.x1);
42273 };
42274
42275 var moveDragButton = function(){
42276 dragButton.style.left = (handle.x1+handle.x2)/2 - $(dragButton).width()/2 + "px";
42277 };
42278
42279 var leftHandle = document.createElement("div");
42280 leftHandle.title = GeoTemConfig.getString('leftHandle');
42281 leftHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "leftHandle.png" + ")";
42282 leftHandle.setAttribute('class', 'plotHandle plotHandleIcon');
42283 leftHandle.style.visibility = "visible";
42284 $(fuzzyTimeline.gui.plotDiv).append(leftHandle);
42285 moveLeftHandle();
42286 leftHandle.style.top = plotHeight/2-$(leftHandle).height()/2 + "px";
42287
42288 var rightHandle = document.createElement("div");
42289 rightHandle.title = GeoTemConfig.getString('leftHandle');
42290 rightHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "rightHandle.png" + ")";
42291 rightHandle.setAttribute('class', 'plotHandle plotHandleIcon');
42292 rightHandle.style.visibility = "visible";
42293 moveRightHandle();
42294 $(fuzzyTimeline.gui.plotDiv).append(rightHandle);
42295
42296 rightHandle.style.top = plotHeight/2-$(rightHandle).height()/2 + "px";
42297
42298 var handleBox = document.createElement("div");
42299 $(fuzzyTimeline.gui.plotDiv).append(handleBox);
42300 $(handleBox).addClass("plotHandleBox");
42301 resizeHandleBox();
42302 $(handleBox).height(plotHeight);
42303
42304 var dragButton = document.createElement("div");
42305 dragButton.title = GeoTemConfig.getString('dragTimeRange');
42306 dragButton.style.backgroundImage = "url(" + GeoTemConfig.path + "drag.png" + ")";
42307 dragButton.setAttribute('class', 'dragTimeRangeAlt plotHandleIcon');
42308 $(fuzzyTimeline.gui.plotDiv).append(dragButton);
42309 moveDragButton();
42310 dragButton.style.top = plotHeight + "px";
42311
42312 $(leftHandle).mousedown(function(){
42313 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){
42314 var x = eventObj.clientX;
42315 x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft();
42316 if ((x < handle.x2) &&
42317 (x >= plotOffset)){
42318 x = x - leftHandle.offsetWidth;
42319 handle.x1 = x + $(leftHandle).width();
42320
42321 moveLeftHandle();
42322 resizeHandleBox();
42323 moveDragButton();
42324 }
42325 });
42326 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){
42327 fuzzyTimeline.selectByX(handle.x1,handle.x2);
42328 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup");
42329 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove");
42330 });
42331 });
42332
42333 $(rightHandle).mousedown(function(){
42334 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){
42335 var x = eventObj.clientX;
42336 x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft();
42337 x = x - rightHandle.offsetWidth;
42338 if ((x > handle.x1) &&
42339 (x <= plotOffset+plotWidth)){
42340 handle.x2 = x;
42341
42342 moveRightHandle();
42343 resizeHandleBox();
42344 moveDragButton();
42345 }
42346 });
42347 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){
42348 fuzzyTimeline.selectByX(handle.x1,handle.x2);
42349 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup");
42350 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove");
42351 });
42352 });
42353
42354 $(dragButton).mousedown(function(){
42355 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){
42356 var x = eventObj.clientX;
42357 //TODO: for some reason we don't need the scoll offset here
42358 //this should be investigated?
42359 //x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft();
42360 var xdiff = x - $(dragButton).offset().left - $(dragButton).width()/2;
42361 handle.x1 = handle.x1+xdiff;
42362 handle.x2 = handle.x2+xdiff;
42363
42364 moveLeftHandle();
42365 moveRightHandle();
42366 resizeHandleBox();
42367 moveDragButton();
42368 });
42369 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){
42370 if (handle.x1 < plotOffset)
42371 handle.x1 = plotOffset;
42372 if (handle.x2 > plotOffset+plotWidth)
42373 handle.x2 = plotOffset+plotWidth;
42374
42375 moveLeftHandle();
42376 moveRightHandle();
42377 resizeHandleBox();
42378 moveDragButton();
42379
42380 fuzzyTimeline.selectByX(handle.x1,handle.x2);
42381 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup");
42382 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove");
42383 });
42384 });
42385 });
42386 },
42387
42388 clearHandles : function(){
42389 var fuzzyTimeline = this;
42390 $(fuzzyTimeline.gui.plotDiv).find(".plotHandle").remove();
42391 $(fuzzyTimeline.gui.plotDiv).find(".dragTimeRangeAlt").remove();
42392 $(fuzzyTimeline.gui.plotDiv).find(".plotHandleBox").remove();
42393 fuzzyTimeline.handles = [];
42394 //disable buttons
42395 $(fuzzyTimeline.rangeSlider.startAnimation).removeClass("playEnabled").addClass("playDisabled");
42396 $(fuzzyTimeline.rangeSlider.pauseAnimation).removeClass("pauseEnabled").addClass("pauseDisabled");
42397 //stop the animation (if one was running)
42398 fuzzyTimeline.pauseAnimation();
42399 },
42400
42401 startAnimation : function(){
42402 var fuzzyTimeline = this;
42403 fuzzyTimeline.loopFunction = function(steps){
42404 $(fuzzyTimeline.handles).each(function(){
42405 if (typeof steps === "undefined")
42406 steps = 1;
42407
42408 var handle = this;
42409 var x1 = handle.x1;
42410 var x2 = handle.x2;
42411
42412 if (typeof handle.width === "undefined")
42413 handle.width = x2-x1;
42414
42415 var plotWidth = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).width();
42416 var plotOffset = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).getPlotOffset().left;
42417
42418 var plotMax = plotWidth+plotOffset;
42419
42420 //TODO: has to be plotMin
42421 if (!((x1 === plotOffset)&&(x2-x1 <= handle.width))){
42422 x1 += steps;
42423 }
42424 if (x2 <= plotMax){
42425 x2 += steps;
42426 if (x2 > plotMax)
42427 x2 = plotMax;
42428 if (x2-x1 > handle.width){
42429 x1 = x2-handle.width;
42430 }
42431 }
42432 if (x1 >= plotMax){
42433 //TODO: has to be plotMin
42434 x1 = plotOffset;
42435 x2 = plotOffset;
42436 }
42437
42438 handle.x1 = x1;
42439 handle.x2 = x2;
42440
42441 fuzzyTimeline.drawHandles();
42442 fuzzyTimeline.selectByX(handle.x1, handle.x2);
42443 });
42444 };
42445
42446 fuzzyTimeline.loopId = setInterval(function(){
42447 fuzzyTimeline.loopFunction(10);
42448 }, 100);
42449 },
42450
42451 pauseAnimation : function(){
42452 var fuzzyTimeline = this;
42453 clearInterval(fuzzyTimeline.loopId);
42454 $(fuzzyTimeline.handles).each(function(){
42455 var handle = this;
42456 delete handle.width;
42457 });
42458 },
42459
42460 //This function enlargens the plot area
42461 zoomPlot : function(zoomFactor){
42462 var fuzzyTimeline = this;
42463 var oldZoomFactor = fuzzyTimeline.zoomFactor;
42464 fuzzyTimeline.zoomFactor = zoomFactor;
42465 if (zoomFactor > 1){
42466 $(fuzzyTimeline.gui.plotDiv).width(zoomFactor*100+"%");
42467 } else{
42468 $(fuzzyTimeline.gui.plotDiv).width("100%");
42469 }
42470 //leave place for the scrollbar
42471 $(fuzzyTimeline.gui.plotDiv).height(fuzzyTimeline.gui.plotDIVHeight-20);
42472
42473 //fit handles
42474 //this does not make much sense, as the selections are _completely_ different
42475 //for each scale rate, as the objects may reside in different "ticks" of the graph
42476 $(fuzzyTimeline.handles).each(function(){
42477 var handle = this;
42478 handle.x1 = handle.x1 * (zoomFactor/oldZoomFactor);
42479 handle.x2 = handle.x2 * (zoomFactor/oldZoomFactor);
42480 });
42481 }
42482 };
42483 /*
42484 * Overlayloader.js
42485 *
42486 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
42487 *
42488 * This library is free software; you can redistribute it and/or
42489 * modify it under the terms of the GNU Lesser General Public
42490 * License as published by the Free Software Foundation; either
42491 * version 3 of the License, or (at your option) any later version.
42492 *
42493 * This library is distributed in the hope that it will be useful,
42494 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42495 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42496 * Lesser General Public License for more details.
42497 *
42498 * You should have received a copy of the GNU Lesser General Public
42499 * License along with this library; if not, write to the Free Software
42500 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42501 * MA 02110-1301 USA
42502 */
42503
42504 /**
42505 * @class Overlayloader
42506 * Implementation for a Overlayloader UI
42507 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
42508 *
42509 * @param {HTML object} parent div to append the Overlayloader
42510 */
42511 function Overlayloader(parent) {
42512
42513 this.overlayLoader = this;
42514
42515 this.parent = parent;
42516 this.options = parent.options;
42517 this.attachedMapWidgets = parent.attachedMapWidgets;
42518
42519 this.overlays = [];
42520
42521 this.initialize();
42522 }
42523
42524 Overlayloader.prototype = {
42525
42526 show : function() {
42527 this.overlayloaderDiv.style.display = "block";
42528 },
42529
42530 hide : function() {
42531 this.overlayloaderDiv.style.display = "none";
42532 },
42533
42534 initialize : function() {
42535
42536 this.addKMLLoader();
42537 this.addKMZLoader();
42538 this.addArcGISWMSLoader();
42539 this.addXYZLoader();
42540 this.addRomanEmpireLoader();
42541 this.addMapsForFreeWaterLayer();
42542 this.addConfigLoader();
42543
42544 // trigger change event on the select so
42545 // that only the first loader div will be shown
42546 $(this.parent.gui.loaderTypeSelect).change();
42547 },
42548
42549 distributeKML : function(kmlURL) {
42550 var newOverlay = new Object();
42551 newOverlay.name = kmlURL;
42552 newOverlay.layers = [];
42553
42554 $(this.attachedMapWidgets).each(function(){
42555 var newLayer = new OpenLayers.Layer.Vector("KML", {
42556 projection: this.openlayersMap.displayProjection,
42557 strategies: [new OpenLayers.Strategy.Fixed()],
42558 protocol: new OpenLayers.Protocol.HTTP({
42559 url: kmlURL,
42560 format: new OpenLayers.Format.KML({
42561 extractStyles: true,
42562 extractAttributes: true
42563 })
42564 })
42565 });
42566
42567 newOverlay.layers.push({map:this.openlayersMap,layer:newLayer});
42568
42569 this.openlayersMap.addLayer(newLayer);
42570 });
42571
42572 this.overlays.push(newOverlay);
42573 this.parent.gui.refreshOverlayList();
42574 },
42575
42576 distributeKMZ : function(kmzURL) {
42577 var newOverlay = new Object();
42578 newOverlay.name = kmzURL;
42579 newOverlay.layers = [];
42580
42581 $(this.attachedMapWidgets).each(function(){
42582 var newLayer = new OpenLayers.Layer.Vector("KML", {
42583 projection: this.openlayersMap.displayProjection,
42584 strategies: [new OpenLayers.Strategy.Fixed()],
42585 format: OpenLayers.Format.KML,
42586 extractAttributes: true
42587 });
42588
42589 newOverlay.layers.push({map:this.openlayersMap,layer:newLayer});
42590
42591 var map = this.openlayersMap;
42592
42593 GeoTemConfig.getKmz(kmzURL, function(kmlDoms){
42594 $(kmlDoms).each(function(){
42595 var kml = new OpenLayers.Format.KML().read(this);
42596 newLayer.addFeatures(kml);
42597 map.addLayer(newLayer);
42598 });
42599 });
42600 });
42601
42602 this.overlays.push(newOverlay);
42603 this.parent.gui.refreshOverlayList();
42604 },
42605
42606 distributeArcGISWMS : function(wmsURL, wmsLayer) {
42607 var newOverlay = new Object();
42608 newOverlay.name = wmsURL + " - " + wmsLayer;
42609 newOverlay.layers = [];
42610
42611 var newLayer = new OpenLayers.Layer.WMS("ArcGIS WMS label", wmsURL, {
42612 layers: wmsLayer,
42613 format: "image/png",
42614 transparent: "true"
42615 }
42616 ,{
42617 displayOutsideMaxExtent: true,
42618 isBaseLayer: false,
42619 projection : "EPSG:3857"
42620 }
42621 );
42622
42623 newLayer.setIsBaseLayer(false);
42624 $(this.attachedMapWidgets).each(function(){
42625 this.openlayersMap.addLayer(newLayer);
42626 newOverlay.layers.push({map:this.openlayersMap,layer:newLayer});
42627 });
42628
42629 this.overlays.push(newOverlay);
42630 this.parent.gui.refreshOverlayList();
42631 },
42632
42633 distributeXYZ : function(xyzURL,zoomOffset) {
42634 var newOverlay = new Object();
42635 newOverlay.name = xyzURL;
42636 newOverlay.layers = [];
42637
42638 var newLayer = new OpenLayers.Layer.XYZ(
42639 "XYZ Layer",
42640 [
42641 xyzURL
42642 ], {
42643 sphericalMercator: true,
42644 transitionEffect: "resize",
42645 buffer: 1,
42646 numZoomLevels: 12,
42647 transparent : true,
42648 isBaseLayer : false,
42649 zoomOffset:zoomOffset?zoomOffset:0
42650 }
42651 );
42652
42653 newLayer.setIsBaseLayer(false);
42654 $(this.attachedMapWidgets).each(function(){
42655 this.openlayersMap.addLayer(newLayer);
42656 newOverlay.layers.push({map:this.openlayersMap,layer:newLayer});
42657 });
42658
42659 this.overlays.push(newOverlay);
42660 this.parent.gui.refreshOverlayList();
42661 },
42662
42663 addKMLLoader : function() {
42664 $(this.parent.gui.loaderTypeSelect).append("<option value='KMLLoader'>KML File URL</option>");
42665
42666 this.KMLLoaderTab = document.createElement("div");
42667 $(this.KMLLoaderTab).attr("id","KMLLoader");
42668
42669 this.kmlURL = document.createElement("input");
42670 $(this.kmlURL).attr("type","text");
42671 $(this.KMLLoaderTab).append(this.kmlURL);
42672
42673 this.loadKMLButton = document.createElement("button");
42674 $(this.loadKMLButton).text("load KML");
42675 $(this.KMLLoaderTab).append(this.loadKMLButton);
42676
42677 $(this.loadKMLButton).click($.proxy(function(){
42678 var kmlURL = $(this.kmlURL).val();
42679 if (kmlURL.length == 0)
42680 return;
42681 if (typeof GeoTemConfig.proxy != 'undefined')
42682 kmlURL = GeoTemConfig.proxy + kmlURL;
42683
42684 this.distributeKML(kmlURL);
42685 },this));
42686
42687 $(this.parent.gui.loaders).append(this.KMLLoaderTab);
42688 },
42689
42690 addKMZLoader : function() {
42691 $(this.parent.gui.loaderTypeSelect).append("<option value='KMZLoader'>KMZ File URL</option>");
42692
42693 this.KMZLoaderTab = document.createElement("div");
42694 $(this.KMZLoaderTab).attr("id","KMZLoader");
42695
42696 this.kmzURL = document.createElement("input");
42697 $(this.kmzURL).attr("type","text");
42698 $(this.KMZLoaderTab).append(this.kmzURL);
42699
42700 this.loadKMZButton = document.createElement("button");
42701 $(this.loadKMZButton).text("load KMZ");
42702 $(this.KMZLoaderTab).append(this.loadKMZButton);
42703
42704 $(this.loadKMZButton).click($.proxy(function(){
42705 var kmzURL = $(this.kmzURL).val();
42706 if (kmzURL.length == 0)
42707 return;
42708 if (typeof GeoTemConfig.proxy != 'undefined')
42709 kmzURL = GeoTemConfig.proxy + kmzURL;
42710
42711 this.distributeKMZ(kmzURL);
42712 },this));
42713
42714 $(this.parent.gui.loaders).append(this.KMZLoaderTab);
42715 },
42716
42717 addArcGISWMSLoader : function() {
42718 $(this.parent.gui.loaderTypeSelect).append("<option value='ArcGISWMSLoader'>ArcGIS WMS</option>");
42719
42720 this.ArcGISWMSLoaderTab = document.createElement("div");
42721 $(this.ArcGISWMSLoaderTab).attr("id","ArcGISWMSLoader");
42722
42723 $(this.ArcGISWMSLoaderTab).append("URL: ");
42724
42725 this.wmsURL = document.createElement("input");
42726 $(this.wmsURL).attr("type","text");
42727 $(this.ArcGISWMSLoaderTab).append(this.wmsURL);
42728
42729 $(this.ArcGISWMSLoaderTab).append("Layer: ");
42730
42731 this.wmsLayer = document.createElement("input");
42732 $(this.wmsLayer).attr("type","text");
42733 $(this.ArcGISWMSLoaderTab).append(this.wmsLayer);
42734
42735 this.loadArcGISWMSButton = document.createElement("button");
42736 $(this.loadArcGISWMSButton).text("load Layer");
42737 $(this.ArcGISWMSLoaderTab).append(this.loadArcGISWMSButton);
42738
42739 $(this.loadArcGISWMSButton).click($.proxy(function(){
42740 var wmsURL = $(this.wmsURL).val();
42741 var wmsLayer = $(this.wmsLayer).val();
42742 if (wmsURL.length == 0)
42743 return;
42744
42745 this.distributeArcGISWMS(wmsURL, wmsLayer);
42746 },this));
42747
42748 $(this.parent.gui.loaders).append(this.ArcGISWMSLoaderTab);
42749 },
42750
42751 addXYZLoader : function() {
42752 $(this.parent.gui.loaderTypeSelect).append("<option value='XYZLoader'>XYZ Layer</option>");
42753
42754 this.XYZLoaderTab = document.createElement("div");
42755 $(this.XYZLoaderTab).attr("id","XYZLoader");
42756
42757 $(this.XYZLoaderTab).append("URL (with x,y,z variables): ");
42758
42759 this.xyzURL = document.createElement("input");
42760 $(this.xyzURL).attr("type","text");
42761 $(this.XYZLoaderTab).append(this.xyzURL);
42762
42763 this.loadXYZButton = document.createElement("button");
42764 $(this.loadXYZButton).text("load Layer");
42765 $(this.XYZLoaderTab).append(this.loadXYZButton);
42766
42767 $(this.loadXYZButton).click($.proxy(function(){
42768 var xyzURL = $(this.xyzURL).val();
42769 if (xyzURL.length == 0)
42770 return;
42771
42772 this.distributeXYZ(xyzURL);
42773 },this));
42774
42775 $(this.parent.gui.loaders).append(this.XYZLoaderTab);
42776 },
42777
42778 addRomanEmpireLoader : function() {
42779 $(this.parent.gui.loaderTypeSelect).append("<option value='RomanEmpireLoader'>Roman Empire</option>");
42780
42781 this.RomanEmpireLoaderTab = document.createElement("div");
42782 $(this.RomanEmpireLoaderTab).attr("id","RomanEmpireLoader");
42783
42784 this.loadRomanEmpireButton = document.createElement("button");
42785 $(this.loadRomanEmpireButton).text("load Layer");
42786 $(this.RomanEmpireLoaderTab).append(this.loadRomanEmpireButton);
42787
42788 $(this.loadRomanEmpireButton).click($.proxy(function(){
42789 this.distributeXYZ("http://pelagios.dme.ait.ac.at/tilesets/imperium/${z}/${x}/${y}.png",1);
42790 },this));
42791
42792 $(this.parent.gui.loaders).append(this.RomanEmpireLoaderTab);
42793 },
42794
42795 addMapsForFreeWaterLayer : function() {
42796 $(this.parent.gui.loaderTypeSelect).append("<option value='MapsForFreeWaterLayerLoader'>Water Layer (Maps-For-Free)</option>");
42797
42798 this.MapsForFreeWaterTab = document.createElement("div");
42799 $(this.MapsForFreeWaterTab).attr("id","MapsForFreeWaterLayerLoader");
42800
42801 this.loadMapsForFreeWaterLayerButton = document.createElement("button");
42802 $(this.loadMapsForFreeWaterLayerButton).text("load Layer");
42803 $(this.MapsForFreeWaterTab).append(this.loadMapsForFreeWaterLayerButton);
42804
42805 $(this.loadMapsForFreeWaterLayerButton).click($.proxy(function(){
42806 this.distributeXYZ("http://maps-for-free.com/layer/water/z${z}/row${y}/${z}_${x}-${y}.gif",1);
42807 },this));
42808
42809 $(this.parent.gui.loaders).append(this.MapsForFreeWaterTab);
42810 },
42811
42812 addConfigLoader : function() {
42813 if ( (this.parent.options.wms_overlays instanceof Array) &&
42814 (this.parent.options.wms_overlays.length > 0) ){
42815 var overlayloader = this;
42816
42817 $(this.parent.gui.loaderTypeSelect).append("<option value='ConfigLoader'>Other WMS maps</option>");
42818
42819 this.ConfigLoaderTab = document.createElement("div");
42820 $(this.ConfigLoaderTab).attr("id","ConfigLoader");
42821
42822 this.ConfigMapSelect = document.createElement("select");
42823 $(this.parent.options.wms_overlays).each(function(){
42824 var name = this.name, server = this.server, layer = this.layer;
42825 $(overlayloader.ConfigMapSelect).append("<option layer='"+layer+"' server='"+server+"' >"+name+"</option>");
42826 });
42827
42828 $(this.ConfigLoaderTab).append(this.ConfigMapSelect);
42829
42830 this.loadConfigMapButton = document.createElement("button");
42831 $(this.loadConfigMapButton).text("load Layer");
42832 $(this.ConfigLoaderTab).append(this.loadConfigMapButton);
42833
42834 $(this.loadConfigMapButton).click($.proxy(function(){
42835 var server = $(this.ConfigMapSelect).find(":selected").attr("server");
42836 var layer = $(this.ConfigMapSelect).find(":selected").attr("layer");
42837 this.distributeArcGISWMS(server,layer);
42838 },this));
42839
42840 $(this.parent.gui.loaders).append(this.ConfigLoaderTab);
42841 }
42842 }
42843
42844 };
42845 /*
42846 * OverlayloaderConfig.js
42847 *
42848 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
42849 *
42850 * This library is free software; you can redistribute it and/or
42851 * modify it under the terms of the GNU Lesser General Public
42852 * License as published by the Free Software Foundation; either
42853 * version 3 of the License, or (at your option) any later version.
42854 *
42855 * This library is distributed in the hope that it will be useful,
42856 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42857 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42858 * Lesser General Public License for more details.
42859 *
42860 * You should have received a copy of the GNU Lesser General Public
42861 * License along with this library; if not, write to the Free Software
42862 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42863 * MA 02110-1301 USA
42864 */
42865
42866 /**
42867 * @class OverlayloaderConfig
42868 * Overlayloader Configuration File
42869 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
42870 */
42871 function OverlayloaderConfig(options) {
42872
42873 this.options = {
42874 wms_overlays : [
42875 //e.g. {name:'name', server:'url', layer:'layer'},
42876 ],
42877 };
42878 if ( typeof options != 'undefined') {
42879 $.extend(this.options, options);
42880 }
42881
42882 };
42883 /*
42884 * OverlayloaderGui.js
42885 *
42886 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
42887 *
42888 * This library is free software; you can redistribute it and/or
42889 * modify it under the terms of the GNU Lesser General Public
42890 * License as published by the Free Software Foundation; either
42891 * version 3 of the License, or (at your option) any later version.
42892 *
42893 * This library is distributed in the hope that it will be useful,
42894 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42895 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42896 * Lesser General Public License for more details.
42897 *
42898 * You should have received a copy of the GNU Lesser General Public
42899 * License along with this library; if not, write to the Free Software
42900 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42901 * MA 02110-1301 USA
42902 */
42903
42904 /**
42905 * @class OverlayloaderGui
42906 * Overlayloader GUI Implementation
42907 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
42908 *
42909 * @param {OverlayloaderWidget} parent Overlayloader widget object
42910 * @param {HTML object} div parent div to append the Overlayloader gui
42911 * @param {JSON} options Overlayloader configuration
42912 */
42913 function OverlayloaderGui(overlayloader, div, options) {
42914
42915 this.parent = overlayloader;
42916 var overlayloaderGui = this;
42917
42918 this.overlayloaderContainer = div;
42919 this.overlayloaderContainer.style.position = 'relative';
42920
42921 this.loaderTypeSelect = document.createElement("select");
42922 div.appendChild(this.loaderTypeSelect);
42923
42924 this.loaders = document.createElement("div");
42925 div.appendChild(this.loaders);
42926
42927 this.overlayList = document.createElement("div");
42928 div.appendChild(this.overlayList);
42929
42930 $(this.loaderTypeSelect).change(function(){
42931 var activeLoader = $(this).val();
42932 $(overlayloaderGui.loaders).find("div").each(function(){
42933 if ($(this).attr("id") == activeLoader)
42934 $(this).show();
42935 else
42936 $(this).hide();
42937 });
42938 });
42939
42940 this.refreshOverlayList = function(){
42941 var overlayloaderGui = this;
42942
42943 $(overlayloaderGui.overlayList).empty();
42944 $(this.parent.overlayLoader.overlays).each(function(){
42945 var overlay = this;
42946 $(overlayloaderGui.overlayList).append(overlay.name);
42947 var link = document.createElement("a");
42948 $(link).text("(x)");
42949 link.href="";
42950
42951 $(link).click($.proxy(function(){
42952 $(overlay.layers).each(function(){
42953 this.map.removeLayer(this.layer);
42954 });
42955
42956 var overlays = overlayloaderGui.parent.overlayLoader.overlays;
42957
42958 overlays = $.grep(overlays, function(value) {
42959 return overlay != value;
42960 });
42961
42962 overlayloaderGui.parent.overlayLoader.overlays = overlays;
42963
42964 overlayloaderGui.refreshOverlayList();
42965
42966 return(false);
42967 },{overlay:overlay,overlayloaderGui:overlayloaderGui}));
42968 $(overlayloaderGui.overlayList).append(link);
42969 });
42970 };
42971 };
42972 /*
42973 * OverlayloaderWidget.js
42974 *
42975 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
42976 *
42977 * This library is free software; you can redistribute it and/or
42978 * modify it under the terms of the GNU Lesser General Public
42979 * License as published by the Free Software Foundation; either
42980 * version 3 of the License, or (at your option) any later version.
42981 *
42982 * This library is distributed in the hope that it will be useful,
42983 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42984 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42985 * Lesser General Public License for more details.
42986 *
42987 * You should have received a copy of the GNU Lesser General Public
42988 * License along with this library; if not, write to the Free Software
42989 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42990 * MA 02110-1301 USA
42991 */
42992
42993 /**
42994 * @class OverlayloaderWidget
42995 * OverlayloaderWidget Implementation
42996 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
42997 *
42998 * @param {WidgetWrapper} core wrapper for interaction to other widgets
42999 * @param {HTML object} div parent div to append the Overlayloader widget div
43000 * @param {JSON} options user specified configuration that overwrites options in OverlayloaderConfig.js
43001 */
43002 OverlayloaderWidget = function(core, div, options) {
43003
43004 this.core = core;
43005 this.core.setWidget(this);
43006
43007 this.options = (new OverlayloaderConfig(options)).options;
43008 this.gui = new OverlayloaderGui(this, div, this.options);
43009
43010 this.attachedMapWidgets = new Array();
43011
43012 this.overlayLoader = new Overlayloader(this);
43013 }
43014
43015 OverlayloaderWidget.prototype = {
43016
43017 initWidget : function() {
43018
43019 var overlayloaderWidget = this;
43020 },
43021
43022 highlightChanged : function(objects) {
43023 if( !GeoTemConfig.highlightEvents ){
43024 return;
43025 }
43026 },
43027
43028 selectionChanged : function(selection) {
43029 if( !GeoTemConfig.selectionEvents ){
43030 return;
43031 }
43032 },
43033
43034 triggerHighlight : function(item) {
43035 },
43036
43037 tableSelection : function() {
43038 },
43039
43040 deselection : function() {
43041 },
43042
43043 filtering : function() {
43044 },
43045
43046 inverseFiltering : function() {
43047 },
43048
43049 triggerRefining : function() {
43050 },
43051
43052 reset : function() {
43053 },
43054
43055 attachMapWidget : function(widget) {
43056 this.attachedMapWidgets.push(widget);
43057 }
43058 };
43059 /*
43060 * PieChart.js
43061 *
43062 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
43063 *
43064 * This library is free software; you can redistribute it and/or
43065 * modify it under the terms of the GNU Lesser General Public
43066 * License as published by the Free Software Foundation; either
43067 * version 3 of the License, or (at your option) any later version.
43068 *
43069 * This library is distributed in the hope that it will be useful,
43070 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43071 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43072 * Lesser General Public License for more details.
43073 *
43074 * You should have received a copy of the GNU Lesser General Public
43075 * License along with this library; if not, write to the Free Software
43076 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
43077 * MA 02110-1301 USA
43078 */
43079
43080 /**
43081 * @class PieChart
43082 * Implementation for a PieChart
43083 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
43084 *
43085 * @param {HTML object} parent div to append the PieChart
43086 */
43087 function PieChart(parent, watchedDataset, watchedColumn, selectionFunction) {
43088
43089 if ((typeof selectionFunction !== "undefined") &&
43090 (typeof selectionFunction.type !== "undefined") &&
43091 (typeof selectionFunction.categories !== "undefined")){
43092 this.type = selectionFunction.type;
43093 this.categories = selectionFunction.categories;
43094 }
43095 this.pieChart = this;
43096 this.pieChartDiv;
43097 this.preHighlightObjects;
43098 this.highlightedLabel;
43099
43100 this.informationDIV;
43101 this.pieChartLabel;
43102
43103 this.parent = parent;
43104 this.options = parent.options;
43105
43106 this.watchedDatasetObject;
43107 this.watchedDataset = parseInt(watchedDataset);
43108 this.watchColumn = watchedColumn;
43109 if (typeof selectionFunction !== "undefined")
43110 this.selectionFunction = selectionFunction;
43111 else
43112 //default selectionFunction returns value (creates "distinct" piechart)
43113 this.selectionFunction = function(columnData){return columnData;};
43114 }
43115
43116 PieChart.prototype = {
43117
43118 remove : function() {
43119 for (var i = 0; i < this.parent.pieCharts.length; i++){
43120 if (this.parent.pieCharts[i] === this)
43121 this.parent.pieCharts[i] = null;
43122 }
43123 $(this.pieChartDiv).remove();
43124 $(this.informationDIV).remove();
43125 this.parent.redrawPieCharts();
43126 },
43127
43128 refreshLabel : function(){
43129 $(this.pieChartLabel).empty();
43130 $(this.pieChartLabel).append(this.watchedDatasetObject.label + " - " + this.watchColumn);
43131
43132 var c = GeoTemConfig.getColor(this.watchedDataset);
43133 $(this.pieChartLabel).css("color","rgb("+c.r1+","+c.g1+","+c.b1+")");
43134 },
43135
43136 initialize : function() {
43137 var pieChart = this;
43138
43139 if (typeof this.pieChartDiv === "undefined"){
43140 this.informationDIV = document.createElement("div");
43141 this.pieChartLabel = $("<span></span>");
43142 $(this.informationDIV).append(this.pieChartLabel);
43143 this.refreshLabel();
43144
43145 var removeButton = document.createElement("button");
43146 $(this.informationDIV).append(removeButton);
43147 $(removeButton).text("remove");
43148 $(removeButton).click(function(){
43149 pieChart.remove();
43150 });
43151
43152 //only allow editing if it is a "manually" created piechart
43153 //automatic (with a selection function) ones, can lead to numerous problems,
43154 //e.g. too many categories or numeral categories threated as text ones
43155 if ((typeof pieChart.type !== "undefined")&&
43156 (typeof pieChart.categories !== "undefined")){
43157 var editButton = document.createElement("button");
43158 $(this.informationDIV).append(editButton);
43159 $(editButton).text("edit");
43160 $(editButton).click(function(){
43161 var chooser = new PieChartCategoryChooser(
43162 pieChart.parent,
43163 pieChart.parent.options,
43164 pieChart.watchedDataset,
43165 pieChart.watchColumn,
43166 pieChart.type,
43167 pieChart.categories);
43168 });
43169
43170 //add save button
43171 if (pieChart.options.allowLocalStorage){
43172 var saveButton = document.createElement("button");
43173 $(this.informationDIV).append(saveButton);
43174 $(saveButton).text("save");
43175 $(saveButton).click(function(){
43176 $( "<div>" +
43177 "pie chart name : " +
43178 "<input type='text' size=30 id='saveName' class='ui-widget-content ui-corner-all'></input>" +
43179 "</div>").dialog({
43180 width:'auto',
43181 buttons: [
43182 {
43183 text: "save",
43184 click: function(){
43185 var saveName = $("#saveName").val();
43186 var saveObject = new Object();
43187 saveObject.type = pieChart.type;
43188 saveObject.categories = pieChart.categories;
43189 saveObject.columnName = pieChart.watchColumn;
43190 //save to LocalStorage
43191 $.remember({
43192 name:pieChart.options.localStoragePrefix+saveName,
43193 value:saveObject,
43194 json:true
43195 });
43196 $(this).dialog( "close" );
43197 }
43198 }
43199 ]
43200 });
43201
43202 //set value to default (column name)
43203 $("#saveName").val(pieChart.watchColumn);
43204 //TODO: z-index has to be set, as the "tool-bars" of map (.ddbToolbar in style.css)
43205 //also have a z-index of 10000. z-index should be removed from all elements.
43206 $(".ui-dialog").css("z-index",10005);
43207 });
43208 }
43209 }
43210
43211 $(this.parent.gui.pieChartsDiv).append(this.informationDIV);
43212 this.pieChartDiv = document.createElement("div");
43213 $(this.parent.gui.pieChartsDiv).append(this.pieChartDiv);
43214
43215 $(this.pieChartDiv).unbind();
43216 $(this.pieChartDiv).bind("plothover", function (event, pos, item) {
43217 var highlightedLabel;
43218
43219 if (item) {
43220 highlightedLabel = item.series.label;
43221 }
43222 if (highlightedLabel !== pieChart.highlightedLabel){
43223 pieChart.highlightedLabel = highlightedLabel;
43224 pieChart.triggerHighlight(highlightedLabel);
43225 }
43226 });
43227
43228 $(this.pieChartDiv).bind("plotclick", function (event, pos, item) {
43229 if (item) {
43230 //item.series.label contains the column element
43231 pieChart.triggerSelection(item.series.label);
43232 } else {
43233 pieChart.triggerSelection();
43234 }
43235 });
43236 }
43237 },
43238
43239 //check if dataset is still there
43240 checkForDataSet : function() {
43241 var datasets = this.parent.datasets;
43242 if ((typeof datasets !== "undefined") && (typeof this.watchedDatasetObject !== "undefined")){
43243 //check if our data went missing
43244 for (var i = 0; i < datasets.length; i++){
43245 if (datasets[i] === this.watchedDatasetObject){
43246 //if dataset "before" this one was removed, the index changes
43247 if (this.watchedDataset !== i){
43248 //change color to the new one (changes with index!)
43249 this.watchedDataset = i;
43250 this.refreshLabel();
43251 }
43252 return true;
43253 }
43254 }
43255 }
43256 return false;
43257 },
43258
43259 initPieChart : function(dataSets) {
43260 // get dataset object (could not be there on startup, e.g. piechart defined before load completes)
43261 if (typeof this.watchedDatasetObject === "undefined")
43262 this.watchedDatasetObject = this.parent.datasets[this.watchedDataset];
43263
43264 this.initialize();
43265
43266 // if our dataset went missing, remove this piechart
43267 if (!this.checkForDataSet()){
43268 this.remove();
43269 return;
43270 }
43271
43272 var objects = [];
43273 for (var i = 0; i < dataSets.length; i++)
43274 objects.push([]);
43275 objects[this.watchedDataset] = dataSets[this.watchedDataset].objects;
43276
43277 this.preHighlightObjects = objects;
43278 this.redrawPieChart(objects);
43279 },
43280
43281 redrawPieChart : function(objects) {
43282
43283 if (typeof objects === "undefined")
43284 objects = this.preHighlightObjects;
43285
43286 if (this.checkForDataSet(objects)){
43287 var pieChart = this;
43288 if (objects[this.watchedDataset].length === 0)
43289 objects = this.preHighlightObjects;
43290
43291 var calculateSlices = function(dataObjects){
43292 var chartDataCounter = new Object;
43293
43294 $(dataObjects).each(function(){
43295 var columnData = pieChart.parent.getElementData(this, pieChart.watchColumn, pieChart.selectionFunction);
43296
43297 //disregard empty cells
43298 if ( (typeof columnData === "undefined") || (columnData == "") )
43299 return;
43300
43301 var weight = this.weight;
43302
43303 if (typeof chartDataCounter[columnData] === "undefined")
43304 chartDataCounter[columnData] = weight;
43305 else
43306 chartDataCounter[columnData] += weight;
43307 });
43308
43309 var chartData = [];
43310 $.each(chartDataCounter, function(name,val){
43311 //get rgb-color (24bit = 6 hex digits) from hash
43312 var color = '#'+hex_md5(name).substr(0,6);
43313 chartData.push({label:name,data:val,color:color});
43314 });
43315
43316 //sort by count (occurances of category)
43317 var sortByVal = function(a,b){
43318 return (b.data-a.data);
43319 };
43320 chartData.sort(sortByVal);
43321
43322 return chartData;
43323 };
43324
43325 var chartData = calculateSlices(objects[this.watchedDataset]);
43326
43327 if (chartData.length>0){
43328 $(this.pieChartDiv).empty();
43329
43330 //calculate height (flot NEEDS a height)
43331 var parentHeight = $(this.parent.gui.pieChartsDiv).outerHeight(true) - $(this.parent.gui.columnSelectorDiv).outerHeight(true);
43332 var pieChartCount = 0;
43333 $(this.parent.pieCharts).each(function(){
43334 if (this instanceof PieChart)
43335 pieChartCount++;
43336 });
43337 var height = (parentHeight/pieChartCount) - $(this.informationDIV).outerHeight(true);
43338 if (pieChart.options.restrictPieChartSize !== false)
43339 height = Math.min(height, $(window).height() * pieChart.options.restrictPieChartSize);
43340 $(this.pieChartDiv).height(height);
43341
43342 $.plot($(this.pieChartDiv), chartData,
43343 {
43344 series: {
43345 // Make this a pie chart.
43346 pie: {
43347 show:true
43348 }
43349 },
43350 legend: { show:true, position: 'se' },
43351 grid: {
43352 hoverable: true,
43353 clickable: true
43354 },
43355 tooltip: true,
43356 tooltipOpts: {
43357 content: "%s %p.1%"
43358 }
43359 }
43360 );
43361 }
43362 }
43363 },
43364
43365 triggerHighlight : function(columnElement) {
43366 var highlightedObjects = [];
43367 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
43368 highlightedObjects.push([]);
43369
43370 if (this.watchedDataset >= 0)
43371 highlightedObjects[this.watchedDataset] =
43372 this.parent.getElementsByValue(columnElement, this.watchedDataset, this.watchColumn, this.selectionFunction);
43373 else
43374 highlightedObjects[this.watchedDataset] = [];
43375
43376 this.parent.core.triggerHighlight(highlightedObjects);
43377
43378 var pieChart = this;
43379 $(this.parent.pieCharts).each(function(){
43380 if (this instanceof PieChart && (this !== pieChart)){
43381 if (this.watchedDataset === pieChart.watchedDataset)
43382 this.redrawPieChart(highlightedObjects);
43383 }
43384 });
43385 },
43386
43387 triggerSelection : function(columnElement) {
43388 var selectedObjects = [];
43389 for (var i = 0; i < GeoTemConfig.datasets.length; i++)
43390 selectedObjects.push([]);
43391
43392 var selection;
43393 if (typeof columnElement !== "undefined"){
43394 selectedObjects[this.watchedDataset] =
43395 this.parent.getElementsByValue(columnElement, this.watchedDataset, this.watchColumn, this.selectionFunction);
43396 selection = new Selection(selectedObjects, this);
43397 } else {
43398 selection = new Selection(selectedObjects);
43399 }
43400
43401 this.parent.core.triggerSelection(selection);
43402
43403 if (!selection.valid()){
43404 selection.loadAllObjects();
43405 //"undo" selection (click next to piechart)
43406 //so also redraw this dataset
43407 this.preHighlightObjects = selection.objects;
43408 this.redrawPieChart(selection.objects);
43409 }
43410
43411 var pieChart = this;
43412 $(this.parent.pieCharts).each(function(){
43413 if (this instanceof PieChart && (this !== pieChart)){
43414 if (this.watchedDataset === pieChart.watchedDataset){
43415 this.preHighlightObjects = selection.objects;
43416 this.redrawPieChart(selection.objects);
43417 }
43418 }
43419 });
43420 },
43421
43422 deselection : function() {
43423 },
43424
43425 filtering : function() {
43426 },
43427
43428 inverseFiltering : function() {
43429 },
43430
43431 triggerRefining : function() {
43432 },
43433
43434 reset : function() {
43435 },
43436
43437 show : function() {
43438 },
43439
43440 hide : function() {
43441 }
43442 };
43443 /*
43444 * PieChartCategoryChooser.js
43445 *
43446 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
43447 *
43448 * This library is free software; you can redistribute it and/or
43449 * modify it under the terms of the GNU Lesser General Public
43450 * License as published by the Free Software Foundation; either
43451 * version 3 of the License, or (at your option) any later version.
43452 *
43453 * This library is distributed in the hope that it will be useful,
43454 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43455 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43456 * Lesser General Public License for more details.
43457 *
43458 * You should have received a copy of the GNU Lesser General Public
43459 * License along with this library; if not, write to the Free Software
43460 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
43461 * MA 02110-1301 USA
43462 */
43463
43464 /**
43465 * @class PieChartCategoryChooser
43466 * PieChart dialog for category creation
43467 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
43468 *
43469 * @param {PieChartWidget} parent PieChart widget object
43470 * @param {JSON} options PieChart configuration
43471 * @param {number} datasetIndex index of the dataset
43472 * @param {String} columnName name of the column
43473 */
43474
43475 function PieChartCategoryChooser(pieChart, options, datasetIndex, columnName, type, categories) {
43476
43477 var pieChartCategoryChooser = this;
43478
43479 this.parent = pieChart;
43480 this.options = options;
43481 this.datasetIndex = parseInt(datasetIndex);
43482 this.columnName = columnName;
43483 this.chartData;
43484
43485 this.dialog = $("<div></div>");
43486 this.dialog.html("").dialog({modal: true}).dialog('open');
43487
43488 //to asure that the dialog is above (z-index of) the toolbars
43489 $(".ui-front").css("z-index","10001");
43490
43491 var allNumeric = this.loadValues(datasetIndex, columnName);
43492
43493 if (typeof allNumeric === "undefined")
43494 return;
43495 if (allNumeric === true){
43496 this.createNumeralBasedChooser(this.chartData, categories);
43497 } else {
43498 this.createTextBasedChooser(this.chartData, categories);
43499 }
43500 };
43501
43502 PieChartCategoryChooser.prototype = {
43503
43504 loadValues : function(datasetIndex, columnName){
43505 var pieChartCategoryChooser = this;
43506
43507 var allNumeric = true;
43508 pieChartCategoryChooser.chartData = [];
43509 var chartData = pieChartCategoryChooser.chartData;
43510 $(GeoTemConfig.datasets[datasetIndex].objects).each(function(){
43511 var columnData =
43512 pieChartCategoryChooser.parent.getElementData(this, columnName);
43513
43514 if (isNaN(parseFloat(columnData)))
43515 allNumeric = false;
43516
43517 if ($.inArray(columnData, chartData) == -1)
43518 chartData.push(columnData);
43519 });
43520
43521 if (chartData.length === 0)
43522 return;
43523 else
43524 return allNumeric;
43525 },
43526
43527 createTextBasedChooser : function(chartData, categories){
43528 var pieChartCategoryChooser = this;
43529
43530 var addCategory = function(name,elements){
43531 var newCategoryContainer = document.createElement("fieldset");
43532 var newCategoryLegend = document.createElement("legend");
43533 var newCategoryName = document.createElement("input");
43534 $(newCategoryName).width("80%");
43535 newCategoryName.type = "text";
43536 newCategoryName.value = name;
43537 var newCategoryRemove = document.createElement("button");
43538 $(newCategoryRemove).text("X");
43539 $(newCategoryRemove).click(function(){
43540 $(newCategoryContainer).find("li").each(function(){
43541 //move all elements to unselected list
43542 //("unselected" is defined below)
43543 //prepend so the items appear on top
43544 $(this).prependTo(unselected);
43545 });
43546 //and remove this category
43547 $(newCategoryContainer).remove();
43548 });
43549 $(newCategoryLegend).append(newCategoryName);
43550 $(newCategoryLegend).append(newCategoryRemove);
43551 $(newCategoryContainer).append(newCategoryLegend);
43552 $(newCategoryContainer).width("200px");
43553 $(newCategoryContainer).css("float","left");
43554 var newCategory = document.createElement("ul");
43555 $(newCategory).addClass("connectedSortable");
43556 $(newCategory).css("background", "#eee");
43557 newCategoryContainer.appendChild(newCategory);
43558 $(newCategory).append("<br/>");
43559 cell.appendChild(newCategoryContainer);
43560 //if there are pre-selected elements (e.g. "edit")
43561 //add them and remove them from unselected value list
43562 if (typeof elements !== "undefined"){
43563 $(elements).each(function(){
43564 var value = this;
43565 //add to category
43566 $(newCategory).append("<li>"+value+"</li>");
43567 //remove from unselected list
43568 $(unselected).find("li").filter(function(){
43569 return ($(this).text() === ""+value);
43570 }).remove();
43571 });
43572 }
43573
43574 $( ".connectedSortable" ).sortable({
43575 connectWith: ".connectedSortable"
43576 }).disableSelection();
43577 };
43578
43579 var table = document.createElement("table");
43580 var row = document.createElement("tr");
43581 table.appendChild(row);
43582 var cell = document.createElement("td");
43583 row.appendChild(cell);
43584 cell = document.createElement("td");
43585 row.appendChild(cell);
43586 var addCategoryButton = document.createElement("button");
43587 $(addCategoryButton).text("add new category");
43588 cell.appendChild(addCategoryButton);
43589 var applyCategoryButton = document.createElement("button");
43590 $(applyCategoryButton).text("apply");
43591 cell.appendChild(applyCategoryButton);
43592
43593 row = document.createElement("tr");
43594 table.appendChild(row);
43595 cell = document.createElement("td");
43596 row.appendChild(cell);
43597 var unselected = document.createElement("ul");
43598 $(unselected).addClass("connectedSortable");
43599 cell.appendChild(unselected);
43600 cell = document.createElement("td");
43601 $(cell).attr("valign","top");
43602 $(cell).width("100%");
43603 row.appendChild(cell);
43604
43605 this.dialog.append(table);
43606
43607 $( ".connectedSortable" ).sortable({
43608 connectWith: ".connectedSortable"
43609 }).disableSelection();
43610
43611 $(chartData).each(function(){
43612 $(unselected).append("<li class='ui-state-default'>"+this+"</li>");
43613 });
43614
43615 if (typeof categories !== "undefined"){
43616 $(categories).each(function(){
43617 var category = this;
43618 addCategory(category.label, category.values);
43619 });
43620 }
43621
43622 $(addCategoryButton).click(function(){addCategory();});
43623
43624 $(applyCategoryButton).click(function(){
43625 var categories = [];
43626 $(cell).children().each(function(){
43627 var label = $(this).find("legend > input").val();
43628 var values = [];
43629 $(this).find("li").each(function(){
43630 values.push($(this).text());
43631 });
43632
43633 categories.push({label:label,values:values});
43634 });
43635
43636 var values = [];
43637 $(unselected).find("li").each(function(){
43638 values.push($(this).text());
43639 });
43640
43641 categories.push({label:"other",values:values});
43642
43643 //create pie chart
43644 pieChartCategoryChooser.parent.addCategorizedPieChart(
43645 pieChartCategoryChooser.datasetIndex, pieChartCategoryChooser.columnName,
43646 "text", categories);
43647
43648 //close dialog
43649 $(pieChartCategoryChooser.dialog).dialog("close");
43650 });
43651
43652 //set dialog size
43653 var wWidth = $(window).width();
43654 var dWidth = wWidth * 0.9;
43655 var wHeight = $(window).height();
43656 var dHeight = wHeight * 0.9;
43657 $(this.dialog).dialog("option", "width", dWidth);
43658 $(this.dialog).dialog("option", "height", dHeight);
43659 },
43660
43661 createNumeralBasedChooser : function(chartData, existingCategories){
43662 var numericChartData = [];
43663 for (var i = 0; i < chartData.length; i++){
43664 numericChartData.push(parseFloat(chartData[i]));
43665 }
43666 chartData = numericChartData;
43667 chartData = chartData.sort(function sortNumber(a,b){
43668 return a - b;
43669 });
43670
43671 var min = chartData[0];
43672 var max = chartData[chartData.length-1];
43673 //find minimum step width that is needed
43674 //(otherwise there could be steps that contain more than one element)
43675 var minStep=max-min;
43676 for (var i = 1; i < chartData.length; i++){
43677 var thisStep = chartData[i]-chartData[i-1];
43678 if ((thisStep) < minStep)
43679 minStep = thisStep;
43680 }
43681
43682 var pieChartCategoryChooser = this;
43683
43684 var addCategoryButton = document.createElement("button");
43685 $(addCategoryButton).text("add new category");
43686 this.dialog.append(addCategoryButton);
43687 var applyCategoryButton = document.createElement("button");
43688 $(applyCategoryButton).text("apply");
43689 this.dialog.append(applyCategoryButton);
43690 this.dialog.append("tip: use left/right arrow key for finer adjustment");
43691
43692 var table = document.createElement("table");
43693 row = document.createElement("tr");
43694 table.appendChild(row);
43695 cell = document.createElement("td");
43696 row.appendChild(cell);
43697 cell.colSpan = 2;
43698 var slider = document.createElement("div");
43699 cell.appendChild(slider);
43700 var handles = [];
43701 var categories = [];
43702
43703 row = document.createElement("tr");
43704 table.appendChild(row);
43705 cell = document.createElement("td");
43706 $(cell).attr("valign","top");
43707 row.appendChild(cell);
43708 var unselected = document.createElement("ul");
43709 cell.appendChild(unselected);
43710
43711 cell = document.createElement("td");
43712 $(cell).attr("valign","top");
43713 $(cell).width("100%");
43714 row.appendChild(cell);
43715
43716 this.dialog.append(table);
43717
43718 $(chartData).each(function(){
43719 $(unselected).append("<li class='ui-state-default'>"+this+"</li>");
43720 });
43721
43722 var addCategory = function(boundary){
43723 //check if another handle can be added
43724 if ((handles.length>0) && (handles[handles.length-1] === max))
43725 return false;
43726 //destroy old slider (has to be recreated to show the new handle)
43727 if (handles.length>0)
43728 $(slider).slider("destroy");
43729
43730 if (typeof boundary === "undefined")
43731 boundary = max;
43732 handles.push(boundary);
43733
43734 $(slider).slider({
43735 min:min,
43736 max:max,
43737 step:minStep,
43738 values: handles
43739 });
43740
43741 var placeValues = function(){
43742 $(unselected).find("li").remove();
43743 $(cell).children().find("li").remove();
43744
43745 var j = 0, i = 0;
43746 for (; i < chartData.length; i++){
43747 if (chartData[i]>handles[j])
43748 j++;
43749 if (j == handles.length)
43750 break;
43751 $(categories[j]).append("<li class='ui-state-default'>"+chartData[i]+"</li>");
43752 }
43753 for (; i < chartData.length; i++){
43754 $(unselected).append("<li class='ui-state-default'>"+chartData[i]+"</li>");
43755 }
43756 };
43757
43758 $(slider).on( "slide", function( event, ui ){
43759 var last = min;
43760 //check whether handle values are increasing
43761 for(var i = 0; i < ui.values.length; i++){
43762 if (ui.values[i]<last)
43763 return false;
43764 last = ui.values[i];
43765 }
43766 handles = ui.values;
43767 for(var i = 0; i < handles.length; i++){
43768 $(categories[i]).parent().find("legend").text("<="+handles[i]);
43769 }
43770
43771 placeValues();
43772 });
43773
43774 var newCategoryContainer = document.createElement("fieldset");
43775 $(newCategoryContainer).append("<legend><="+boundary+"</legend>");
43776 $(newCategoryContainer).width("188px");
43777 $(newCategoryContainer).css("float","left");
43778 var newCategory = document.createElement("ul");
43779 $(newCategory).addClass("connectedSortable");
43780 $(newCategory).css("background", "#eee");
43781 newCategoryContainer.appendChild(newCategory);
43782 cell.appendChild(newCategoryContainer);
43783 categories.push(newCategory);
43784
43785 placeValues();
43786 };
43787
43788 $(addCategoryButton).click(function(){addCategory();});
43789
43790 if (typeof existingCategories !== "undefined"){
43791 $(existingCategories).each(function(){
43792 var boundary = this;
43793 addCategory(boundary);
43794 });
43795 }
43796
43797 $(applyCategoryButton).click(function(){
43798 var categorieBoundaries = handles;
43799
43800 //create pie chart
43801 pieChartCategoryChooser.parent.addCategorizedPieChart(
43802 pieChartCategoryChooser.datasetIndex, pieChartCategoryChooser.columnName,
43803 "numeral", categorieBoundaries);
43804
43805 //close dialog
43806 $(pieChartCategoryChooser.dialog).dialog("close");
43807 });
43808
43809 //set dialog size
43810 var wWidth = $(window).width();
43811 var dWidth = wWidth * 0.9;
43812 var wHeight = $(window).height();
43813 var dHeight = wHeight * 0.9;
43814 $(this.dialog).dialog("option", "width", dWidth);
43815 $(this.dialog).dialog("option", "height", dHeight);
43816 }
43817 };
43818 /*
43819 * PieChartConfig.js
43820 *
43821 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
43822 *
43823 * This library is free software; you can redistribute it and/or
43824 * modify it under the terms of the GNU Lesser General Public
43825 * License as published by the Free Software Foundation; either
43826 * version 3 of the License, or (at your option) any later version.
43827 *
43828 * This library is distributed in the hope that it will be useful,
43829 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43830 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43831 * Lesser General Public License for more details.
43832 *
43833 * You should have received a copy of the GNU Lesser General Public
43834 * License along with this library; if not, write to the Free Software
43835 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
43836 * MA 02110-1301 USA
43837 */
43838
43839 /**
43840 * @class PieChartConfig
43841 * PieChart Configuration File
43842 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
43843 */
43844 function PieChartConfig(options) {
43845
43846 this.options = {
43847 restrictPieChartSize : 0.25, // restrict size to percantage of window size (false for no restriction)
43848 localStoragePrefix : "GeoBrowser_PieChart_", // prefix for value name in LocalStorage
43849 allowLocalStorage : true, //whether LocalStorage save and load should be allowed (and buttons shown)
43850 };
43851 if ( typeof options != 'undefined') {
43852 $.extend(this.options, options);
43853 }
43854
43855 };
43856 /*
43857 * PieChartGui.js
43858 *
43859 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
43860 *
43861 * This library is free software; you can redistribute it and/or
43862 * modify it under the terms of the GNU Lesser General Public
43863 * License as published by the Free Software Foundation; either
43864 * version 3 of the License, or (at your option) any later version.
43865 *
43866 * This library is distributed in the hope that it will be useful,
43867 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43868 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43869 * Lesser General Public License for more details.
43870 *
43871 * You should have received a copy of the GNU Lesser General Public
43872 * License along with this library; if not, write to the Free Software
43873 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
43874 * MA 02110-1301 USA
43875 */
43876
43877 /**
43878 * @class PieChartGui
43879 * PieChart GUI Implementation
43880 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
43881 *
43882 * @param {PieChartWidget} parent PieChart widget object
43883 * @param {HTML object} div parent div to append the PieChart gui
43884 * @param {JSON} options PieChart configuration
43885 */
43886 function PieChartGui(pieChart, div, options) {
43887
43888 this.parent = pieChart;
43889 this.options = options;
43890 var pieChartGui = this;
43891
43892 this.pieChartContainer = div;
43893 this.pieChartContainer.style.position = 'relative';
43894
43895 this.columnSelectorDiv = document.createElement("div");
43896 div.appendChild(this.columnSelectorDiv);
43897 this.datasetSelect = document.createElement("select");
43898 $(this.datasetSelect).change(function(event){
43899 if (typeof pieChartGui.parent.datasets !== "undefined"){
43900 var dataset = pieChartGui.parent.datasets[$(pieChartGui.datasetSelect).val()];
43901 if (dataset.objects.length > 0){
43902 //This implies that the dataObjects are homogenous
43903 var firstObject = dataset.objects[0];
43904 var firstTableContent = firstObject.tableContent;
43905 $(pieChartGui.columnSelect).empty();
43906
43907 $(pieChartGui.columnSelect).append("<optgroup label='saved'>");
43908
43909 for(var key in localStorage){
43910 //TODO: this is a somewhat bad idea, as it is used in multiple widgets.
43911 //A global GeoTemCo option "prefix" could be better. But still..
43912 var prefix = pieChartGui.options.localStoragePrefix;
43913 if (key.startsWith(prefix)){
43914 var saveObject = $.remember({name:key,json:true});
43915 var label = key.substring(prefix.length);
43916 //small safety-check: if the column is not part of this dataset, don't show it
43917 if (typeof firstTableContent[saveObject.columnName] !== "undefined")
43918 $(pieChartGui.columnSelect).append("<option isSaved=1 value='"+label+"'>"+decodeURIComponent(label)+"</option>");
43919 }
43920 }
43921 $(pieChartGui.columnSelect).append("</optgroup>");
43922
43923 $(pieChartGui.columnSelect).append("<optgroup label='new'>");
43924 for (var attribute in firstTableContent) {
43925 $(pieChartGui.columnSelect).append("<option value='"+attribute+"'>"+attribute+"</option>");
43926 }
43927 if (firstObject.isTemporal)
43928 $(pieChartGui.columnSelect).append("<option value='dates[0].date'>date</option>");
43929 if (typeof firstObject.locations[0] !== "undefined"){
43930 $(pieChartGui.columnSelect).append("<option value='locations[0].latitude'>lat</option>");
43931 $(pieChartGui.columnSelect).append("<option value='locations[0].longitude'>lon</option>");
43932 }
43933 $(pieChartGui.columnSelect).append("</optgroup>");
43934 }
43935 }
43936 });
43937 this.columnSelectorDiv.appendChild(this.datasetSelect);
43938 this.columnSelect = document.createElement("select");
43939 this.columnSelectorDiv.appendChild(this.columnSelect);
43940 this.buttonNewPieChart = document.createElement("button");
43941 $(this.buttonNewPieChart).text("add");
43942 this.columnSelectorDiv.appendChild(this.buttonNewPieChart);
43943 $(this.buttonNewPieChart).click(function(){
43944 //check if this is a local saved pie chart
43945 var isSaved=$(pieChartGui.columnSelect).find("option:selected").first().attr("isSaved");
43946 if ((typeof isSaved === "undefined") || (isSaved!=1)){
43947 //create new pie chart (where each value is its own category)
43948 pieChartGui.parent.addPieChart($(pieChartGui.datasetSelect).val(), $(pieChartGui.columnSelect).val());
43949 } else {
43950 //is local saved, get value
43951 var name = pieChartGui.options.localStoragePrefix + $(pieChartGui.columnSelect).val();
43952 var saveObject = $.remember({name:name,json:true});
43953 if ((typeof saveObject !== "undefined") && (saveObject != null)){
43954 var categories = saveObject.categories;
43955 var type = saveObject.type;
43956 var columnName = saveObject.columnName;
43957
43958 //create pie chart
43959 pieChartGui.parent.addCategorizedPieChart(
43960 $(pieChartGui.datasetSelect).val(), columnName,
43961 type, categories);
43962 }
43963 }
43964 });
43965 this.buttonPieChartCategoryChooser = document.createElement("button");
43966 $(this.buttonPieChartCategoryChooser).text("categorize");
43967 this.columnSelectorDiv.appendChild(this.buttonPieChartCategoryChooser);
43968 $(this.buttonPieChartCategoryChooser).click(function(){
43969 //check if this is a local saved pie chart
43970 var isSaved=$(pieChartGui.columnSelect).find("option:selected").first().attr("isSaved");
43971 if ((typeof isSaved === "undefined") || (isSaved!=1)){
43972 var chooser = new PieChartCategoryChooser( pieChartGui.parent,
43973 pieChartGui.options,
43974 $(pieChartGui.datasetSelect).val(),
43975 $(pieChartGui.columnSelect).val() );
43976 } else {
43977 alert("Saved datasets can not be categorized again. Try loading and editing instead.");
43978 }
43979 });
43980
43981 this.refreshColumnSelector();
43982
43983 this.pieChartsDiv = document.createElement("div");
43984 this.pieChartsDiv.id = "pieChartsDivID";
43985 div.appendChild(this.pieChartsDiv);
43986 $(this.pieChartsDiv).height("100%");
43987 };
43988
43989 PieChartGui.prototype = {
43990
43991 refreshColumnSelector : function(){
43992 $(this.datasetSelect).empty();
43993 $(this.columnSelect).empty();
43994
43995 if ( (typeof this.parent.datasets !== "undefined") && (this.parent.datasets.length > 0)) {
43996 var index = 0;
43997 var pieChartGui = this;
43998 $(this.parent.datasets).each(function(){
43999 $(pieChartGui.datasetSelect).append("<option value="+index+">"+this.label+"</option>");
44000 index++;
44001 });
44002
44003 $(pieChartGui.datasetSelect).change();
44004 }
44005 }
44006 };
44007 /*
44008 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44009 * Digest Algorithm, as defined in RFC 1321.
44010 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44011 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44012 * Distributed under the BSD License
44013 * See http://pajhome.org.uk/crypt/md5 for more info.
44014 */
44015
44016 /*
44017 * Configurable variables. You may need to tweak these to be compatible with
44018 * the server-side, but the defaults work in most cases.
44019 */
44020 var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
44021 var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
44022
44023 /*
44024 * These are the functions you'll usually want to call
44025 * They take string arguments and return either hex or base-64 encoded strings
44026 */
44027 function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
44028 function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
44029 function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
44030 function hex_hmac_md5(k, d)
44031 { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
44032 function b64_hmac_md5(k, d)
44033 { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
44034 function any_hmac_md5(k, d, e)
44035 { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
44036
44037 /*
44038 * Perform a simple self-test to see if the VM is working
44039 */
44040 function md5_vm_test()
44041 {
44042 return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
44043 }
44044
44045 /*
44046 * Calculate the MD5 of a raw string
44047 */
44048 function rstr_md5(s)
44049 {
44050 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
44051 }
44052
44053 /*
44054 * Calculate the HMAC-MD5, of a key and some data (raw strings)
44055 */
44056 function rstr_hmac_md5(key, data)
44057 {
44058 var bkey = rstr2binl(key);
44059 if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
44060
44061 var ipad = Array(16), opad = Array(16);
44062 for(var i = 0; i < 16; i++)
44063 {
44064 ipad[i] = bkey[i] ^ 0x36363636;
44065 opad[i] = bkey[i] ^ 0x5C5C5C5C;
44066 }
44067
44068 var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44069 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
44070 }
44071
44072 /*
44073 * Convert a raw string to a hex string
44074 */
44075 function rstr2hex(input)
44076 {
44077 try { hexcase } catch(e) { hexcase=0; }
44078 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
44079 var output = "";
44080 var x;
44081 for(var i = 0; i < input.length; i++)
44082 {
44083 x = input.charCodeAt(i);
44084 output += hex_tab.charAt((x >>> 4) & 0x0F)
44085 + hex_tab.charAt( x & 0x0F);
44086 }
44087 return output;
44088 }
44089
44090 /*
44091 * Convert a raw string to a base-64 string
44092 */
44093 function rstr2b64(input)
44094 {
44095 try { b64pad } catch(e) { b64pad=''; }
44096 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
44097 var output = "";
44098 var len = input.length;
44099 for(var i = 0; i < len; i += 3)
44100 {
44101 var triplet = (input.charCodeAt(i) << 16)
44102 | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
44103 | (i + 2 < len ? input.charCodeAt(i+2) : 0);
44104 for(var j = 0; j < 4; j++)
44105 {
44106 if(i * 8 + j * 6 > input.length * 8) output += b64pad;
44107 else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
44108 }
44109 }
44110 return output;
44111 }
44112
44113 /*
44114 * Convert a raw string to an arbitrary string encoding
44115 */
44116 function rstr2any(input, encoding)
44117 {
44118 var divisor = encoding.length;
44119 var i, j, q, x, quotient;
44120
44121 /* Convert to an array of 16-bit big-endian values, forming the dividend */
44122 var dividend = Array(Math.ceil(input.length / 2));
44123 for(i = 0; i < dividend.length; i++)
44124 {
44125 dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
44126 }
44127
44128 /*
44129 * Repeatedly perform a long division. The binary array forms the dividend,
44130 * the length of the encoding is the divisor. Once computed, the quotient
44131 * forms the dividend for the next step. All remainders are stored for later
44132 * use.
44133 */
44134 var full_length = Math.ceil(input.length * 8 /
44135 (Math.log(encoding.length) / Math.log(2)));
44136 var remainders = Array(full_length);
44137 for(j = 0; j < full_length; j++)
44138 {
44139 quotient = Array();
44140 x = 0;
44141 for(i = 0; i < dividend.length; i++)
44142 {
44143 x = (x << 16) + dividend[i];
44144 q = Math.floor(x / divisor);
44145 x -= q * divisor;
44146 if(quotient.length > 0 || q > 0)
44147 quotient[quotient.length] = q;
44148 }
44149 remainders[j] = x;
44150 dividend = quotient;
44151 }
44152
44153 /* Convert the remainders to the output string */
44154 var output = "";
44155 for(i = remainders.length - 1; i >= 0; i--)
44156 output += encoding.charAt(remainders[i]);
44157
44158 return output;
44159 }
44160
44161 /*
44162 * Encode a string as utf-8.
44163 * For efficiency, this assumes the input is valid utf-16.
44164 */
44165 function str2rstr_utf8(input)
44166 {
44167 var output = "";
44168 var i = -1;
44169 var x, y;
44170
44171 while(++i < input.length)
44172 {
44173 /* Decode utf-16 surrogate pairs */
44174 x = input.charCodeAt(i);
44175 y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
44176 if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
44177 {
44178 x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
44179 i++;
44180 }
44181
44182 /* Encode output as utf-8 */
44183 if(x <= 0x7F)
44184 output += String.fromCharCode(x);
44185 else if(x <= 0x7FF)
44186 output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
44187 0x80 | ( x & 0x3F));
44188 else if(x <= 0xFFFF)
44189 output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
44190 0x80 | ((x >>> 6 ) & 0x3F),
44191 0x80 | ( x & 0x3F));
44192 else if(x <= 0x1FFFFF)
44193 output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
44194 0x80 | ((x >>> 12) & 0x3F),
44195 0x80 | ((x >>> 6 ) & 0x3F),
44196 0x80 | ( x & 0x3F));
44197 }
44198 return output;
44199 }
44200
44201 /*
44202 * Encode a string as utf-16
44203 */
44204 function str2rstr_utf16le(input)
44205 {
44206 var output = "";
44207 for(var i = 0; i < input.length; i++)
44208 output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
44209 (input.charCodeAt(i) >>> 8) & 0xFF);
44210 return output;
44211 }
44212
44213 function str2rstr_utf16be(input)
44214 {
44215 var output = "";
44216 for(var i = 0; i < input.length; i++)
44217 output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
44218 input.charCodeAt(i) & 0xFF);
44219 return output;
44220 }
44221
44222 /*
44223 * Convert a raw string to an array of little-endian words
44224 * Characters >255 have their high-byte silently ignored.
44225 */
44226 function rstr2binl(input)
44227 {
44228 var output = Array(input.length >> 2);
44229 for(var i = 0; i < output.length; i++)
44230 output[i] = 0;
44231 for(var i = 0; i < input.length * 8; i += 8)
44232 output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
44233 return output;
44234 }
44235
44236 /*
44237 * Convert an array of little-endian words to a string
44238 */
44239 function binl2rstr(input)
44240 {
44241 var output = "";
44242 for(var i = 0; i < input.length * 32; i += 8)
44243 output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
44244 return output;
44245 }
44246
44247 /*
44248 * Calculate the MD5 of an array of little-endian words, and a bit length.
44249 */
44250 function binl_md5(x, len)
44251 {
44252 /* append padding */
44253 x[len >> 5] |= 0x80 << ((len) % 32);
44254 x[(((len + 64) >>> 9) << 4) + 14] = len;
44255
44256 var a = 1732584193;
44257 var b = -271733879;
44258 var c = -1732584194;
44259 var d = 271733878;
44260
44261 for(var i = 0; i < x.length; i += 16)
44262 {
44263 var olda = a;
44264 var oldb = b;
44265 var oldc = c;
44266 var oldd = d;
44267
44268 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
44269 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
44270 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
44271 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
44272 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
44273 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
44274 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
44275 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
44276 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
44277 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
44278 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
44279 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
44280 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
44281 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
44282 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
44283 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
44284
44285 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
44286 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
44287 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
44288 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
44289 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
44290 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
44291 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
44292 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
44293 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
44294 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
44295 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
44296 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
44297 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
44298 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
44299 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
44300 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
44301
44302 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
44303 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
44304 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
44305 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
44306 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
44307 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
44308 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
44309 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
44310 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
44311 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
44312 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
44313 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
44314 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
44315 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
44316 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
44317 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
44318
44319 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
44320 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
44321 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
44322 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
44323 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
44324 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
44325 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
44326 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
44327 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
44328 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
44329 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
44330 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
44331 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
44332 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
44333 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
44334 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
44335
44336 a = safe_add(a, olda);
44337 b = safe_add(b, oldb);
44338 c = safe_add(c, oldc);
44339 d = safe_add(d, oldd);
44340 }
44341 return Array(a, b, c, d);
44342 }
44343
44344 /*
44345 * These functions implement the four basic operations the algorithm uses.
44346 */
44347 function md5_cmn(q, a, b, x, s, t)
44348 {
44349 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
44350 }
44351 function md5_ff(a, b, c, d, x, s, t)
44352 {
44353 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44354 }
44355 function md5_gg(a, b, c, d, x, s, t)
44356 {
44357 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44358 }
44359 function md5_hh(a, b, c, d, x, s, t)
44360 {
44361 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44362 }
44363 function md5_ii(a, b, c, d, x, s, t)
44364 {
44365 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44366 }
44367
44368 /*
44369 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
44370 * to work around bugs in some JS interpreters.
44371 */
44372 function safe_add(x, y)
44373 {
44374 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
44375 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
44376 return (msw << 16) | (lsw & 0xFFFF);
44377 }
44378
44379 /*
44380 * Bitwise rotate a 32-bit number to the left.
44381 */
44382 function bit_rol(num, cnt)
44383 {
44384 return (num << cnt) | (num >>> (32 - cnt));
44385 }
44386 /*
44387 * PieChartWidget.js
44388 *
44389 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44390 *
44391 * This library is free software; you can redistribute it and/or
44392 * modify it under the terms of the GNU Lesser General Public
44393 * License as published by the Free Software Foundation; either
44394 * version 3 of the License, or (at your option) any later version.
44395 *
44396 * This library is distributed in the hope that it will be useful,
44397 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44398 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44399 * Lesser General Public License for more details.
44400 *
44401 * You should have received a copy of the GNU Lesser General Public
44402 * License along with this library; if not, write to the Free Software
44403 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44404 * MA 02110-1301 USA
44405 */
44406
44407 /**
44408 * @class PieChartWidget
44409 * PieChartWidget Implementation
44410 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44411 *
44412 * @param {WidgetWrapper} core wrapper for interaction to other widgets
44413 * @param {HTML object} div parent div to append the PieChart widget div
44414 * @param {JSON} options user specified configuration that overwrites options in PieChartConfig.js
44415 */
44416 PieChartWidget = function(core, div, options) {
44417
44418 this.datasets;
44419 this.selected;
44420 this.core = core;
44421 this.core.setWidget(this);
44422
44423 this.options = (new PieChartConfig(options)).options;
44424 this.gui = new PieChartGui(this, div, this.options);
44425
44426 this.pieCharts = [];
44427 }
44428
44429 PieChartWidget.prototype = {
44430
44431 addCategorizedPieChart : function(watchedDataset, watchedColumn, type, categories){
44432 var selectionFunction;
44433 if (type === "text"){
44434 //create selection function for the pie chart
44435 var selectionFunction = function(columnData){
44436 var categoryLabel;
44437 $(categories).each(function(){
44438 if ($.inArray(columnData,this.values) != -1){
44439 categoryLabel = this.label;
44440 //exit .each
44441 return false;
44442 }
44443 if (typeof categoryLabel !== "undefined")
44444 return false;
44445 });
44446
44447 if (typeof categoryLabel === "undefined")
44448 categoryLabel = "unknown";
44449
44450 return categoryLabel;
44451 };
44452 } else if (type === "numeral"){
44453 //create selection function for the pie chart
44454 var selectionFunction = function(columnData){
44455 var categoryLabel;
44456 var columnDataNumeric = parseFloat(columnData);
44457 for (var i = 0; i < categories.length; i++){
44458 if (columnDataNumeric<=categories[i]){
44459 categoryLabel = pieChartCategoryChooser.columnName + "<=" + categories[i];
44460 break;
44461 }
44462 }
44463
44464 if (typeof categoryLabel === "undefined")
44465 categoryLabel = "unknown";
44466
44467 return categoryLabel;
44468 };
44469 } else
44470 return;
44471
44472 //make categories easy accessible for later usage
44473 selectionFunction.type = type;
44474 selectionFunction.categories = categories;
44475
44476 this.addPieChart(watchedDataset, watchedColumn, selectionFunction);
44477 },
44478
44479 addPieChart : function(watchedDataset, watchedColumn, selectionFunction){
44480 var newPieChart = new PieChart(this, watchedDataset, watchedColumn, selectionFunction);
44481 this.pieCharts.push(newPieChart);
44482 if ( (typeof GeoTemConfig.datasets !== "undefined") &&
44483 (GeoTemConfig.datasets.length > watchedDataset) )
44484 newPieChart.initPieChart(GeoTemConfig.datasets);
44485 this.redrawPieCharts(this.selected);
44486 },
44487
44488 initWidget : function(data) {
44489 var piechart = this;
44490 this.datasets = data;
44491 piechart.selected = [];
44492 $(this.datasets).each(function(){
44493 piechart.selected.push(this.objects);
44494 })
44495
44496 this.gui.refreshColumnSelector();
44497
44498 $(this.pieCharts).each(function(){
44499 if (this instanceof PieChart)
44500 this.initPieChart(data);
44501 });
44502 },
44503
44504 redrawPieCharts : function(objects, overwrite) {
44505 $(this.pieCharts).each(function(){
44506 if (this instanceof PieChart){
44507 if ( (typeof overwrite !== "undefined") && overwrite)
44508 this.preHighlightObjects = objects;
44509 this.redrawPieChart(objects);
44510 }
44511 });
44512 },
44513
44514 highlightChanged : function(objects) {
44515 if( !GeoTemConfig.highlightEvents ){
44516 return;
44517 }
44518 if ( (typeof objects === "undefined") || (objects.length == 0) ){
44519 return;
44520 }
44521 this.redrawPieCharts(objects, false);
44522 },
44523
44524 selectionChanged : function(selection) {
44525 if( !GeoTemConfig.selectionEvents ){
44526 return;
44527 }
44528 if (!selection.valid()){
44529 selection.loadAllObjects();
44530 }
44531 var objects = selection.objects;
44532 this.selected = objects;
44533 this.redrawPieCharts(objects, true);
44534 },
44535
44536 getElementData : function(dataObject, watchedColumn, selectionFunction) {
44537 var columnData;
44538 if (watchedColumn.indexOf("[") === -1){
44539 columnData = dataObject[watchedColumn];
44540 if (typeof columnData === "undefined"){
44541 columnData = dataObject.tableContent[watchedColumn];
44542 };
44543 } else {
44544 try {
44545 var columnName = watchedColumn.split("[")[0];
44546 var IndexAndAttribute = watchedColumn.split("[")[1];
44547 if (IndexAndAttribute.indexOf("]") != -1){
44548 var arrayIndex = IndexAndAttribute.split("]")[0];
44549 var attribute = IndexAndAttribute.split("]")[1];
44550
44551 if (typeof attribute === "undefined")
44552 columnData = dataObject[columnName][arrayIndex];
44553 else{
44554 attribute = attribute.split(".")[1];
44555 columnData = dataObject[columnName][arrayIndex][attribute];
44556 }
44557 }
44558 } catch(e) {
44559 if (typeof console !== undefined)
44560 console.error(e);
44561
44562 delete columnData;
44563 }
44564 }
44565
44566 if ( (typeof columnData !== "undefined") && (typeof selectionFunction !== "undefined") )
44567 columnData = selectionFunction(columnData);
44568
44569 return(columnData);
44570 },
44571
44572 getElementsByValue : function(columnValue, watchedDataset, watchedColumn, selectionFunction) {
44573 var elements = [];
44574 var pieChart = this;
44575
44576 $(this.datasets[watchedDataset].objects).each(function(){
44577 var columnData = pieChart.getElementData(this, watchedColumn, selectionFunction);
44578 if (columnData === columnValue)
44579 elements.push(this);
44580 });
44581
44582 return elements;
44583 },
44584 };
44585 /*
44586 * Storytelling.js
44587 *
44588 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44589 *
44590 * This library is free software; you can redistribute it and/or
44591 * modify it under the terms of the GNU Lesser General Public
44592 * License as published by the Free Software Foundation; either
44593 * version 3 of the License, or (at your option) any later version.
44594 *
44595 * This library is distributed in the hope that it will be useful,
44596 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44597 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44598 * Lesser General Public License for more details.
44599 *
44600 * You should have received a copy of the GNU Lesser General Public
44601 * License along with this library; if not, write to the Free Software
44602 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44603 * MA 02110-1301 USA
44604 */
44605
44606 /**
44607 * @class Storytelling
44608 * Implementation of story telling "storage"
44609 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44610 *
44611 * @param {HTML object} parent div to append the Storytelling widget
44612 */
44613 function Storytelling(parent) {
44614
44615 this.index;
44616 this.storytelling = this;
44617
44618 this.parent = parent;
44619 this.options = parent.options;
44620
44621 this.initialize();
44622 }
44623
44624 Storytelling.prototype = {
44625
44626 remove : function() {
44627 },
44628
44629 initialize : function() {
44630 },
44631
44632 triggerHighlight : function(columnElement) {
44633 },
44634
44635 triggerSelection : function(columnElement) {
44636 },
44637
44638 deselection : function() {
44639 },
44640
44641 filtering : function() {
44642 },
44643
44644 inverseFiltering : function() {
44645 },
44646
44647 triggerRefining : function() {
44648 },
44649
44650 reset : function() {
44651 },
44652
44653 show : function() {
44654 },
44655
44656 hide : function() {
44657 }
44658 };
44659 /*
44660 * StorytellingConfig.js
44661 *
44662 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44663 *
44664 * This library is free software; you can redistribute it and/or
44665 * modify it under the terms of the GNU Lesser General Public
44666 * License as published by the Free Software Foundation; either
44667 * version 3 of the License, or (at your option) any later version.
44668 *
44669 * This library is distributed in the hope that it will be useful,
44670 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44671 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44672 * Lesser General Public License for more details.
44673 *
44674 * You should have received a copy of the GNU Lesser General Public
44675 * License along with this library; if not, write to the Free Software
44676 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44677 * MA 02110-1301 USA
44678 */
44679
44680 /**
44681 * @class StorytellingConfig
44682 * Storytelling Configuration File
44683 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44684 */
44685 function StorytellingConfig(options) {
44686
44687 this.options = {
44688 dariahStorage : false,
44689 localStorage : true
44690 };
44691 if ( typeof options != 'undefined') {
44692 $.extend(this.options, options);
44693 }
44694
44695 };
44696 /*
44697 * StorytellingGui.js
44698 *
44699 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44700 *
44701 * This library is free software; you can redistribute it and/or
44702 * modify it under the terms of the GNU Lesser General Public
44703 * License as published by the Free Software Foundation; either
44704 * version 3 of the License, or (at your option) any later version.
44705 *
44706 * This library is distributed in the hope that it will be useful,
44707 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44708 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44709 * Lesser General Public License for more details.
44710 *
44711 * You should have received a copy of the GNU Lesser General Public
44712 * License along with this library; if not, write to the Free Software
44713 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44714 * MA 02110-1301 USA
44715 */
44716
44717 /**
44718 * @class StorytellingGui
44719 * Storytelling GUI Implementation
44720 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44721 *
44722 * @param {StorytellingWidget} parent Storytelling widget object
44723 * @param {HTML object} div parent div to append the Storytelling gui
44724 * @param {JSON} options Storytelling configuration
44725 */
44726 function StorytellingGui(storytelling, div, options) {
44727
44728 this.parent = storytelling;
44729 var storytellingGui = this;
44730
44731 storytellingGui.storytellingContainer = document.createElement('div');
44732 $(div).append(storytellingGui.storytellingContainer);
44733 storytellingGui.storytellingContainer.style.position = 'relative';
44734 };
44735
44736 StorytellingGui.prototype = {
44737 };
44738 /*
44739 * StorytellingWidget.js
44740 *
44741 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44742 *
44743 * This library is free software; you can redistribute it and/or
44744 * modify it under the terms of the GNU Lesser General Public
44745 * License as published by the Free Software Foundation; either
44746 * version 3 of the License, or (at your option) any later version.
44747 *
44748 * This library is distributed in the hope that it will be useful,
44749 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44750 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44751 * Lesser General Public License for more details.
44752 *
44753 * You should have received a copy of the GNU Lesser General Public
44754 * License along with this library; if not, write to the Free Software
44755 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44756 * MA 02110-1301 USA
44757 */
44758
44759 /**
44760 * @class StorytellingWidget
44761 * StorytellingWidget Implementation
44762 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44763 *
44764 * @param {WidgetWrapper} core wrapper for interaction to other widgets
44765 * @param {HTML object} div parent div to append the Storytelling widget div
44766 * @param {JSON} options user specified configuration that overwrites options in StorytellingConfig.js
44767 */
44768 StorytellingWidget = function(core, div, options) {
44769
44770 this.datasets;
44771 this.core = core;
44772 this.core.setWidget(this);
44773 this.currentStatus = new Object();
44774
44775 this.options = (new StorytellingConfig(options)).options;
44776 this.gui = new StorytellingGui(this, div, this.options);
44777
44778 this.datasetLink;
44779
44780 Publisher.Subscribe('mapChanged', this, function(mapName) {
44781 this.client.currentStatus["mapChanged"] = mapName;
44782 this.client.createLink();
44783 });
44784
44785 var currentStatus = $.url().param("currentStatus");
44786 if (typeof currentStatus !== "undefined"){
44787 this.currentStatus = $.deparam(currentStatus);
44788 $.each(this.currentStatus,function(action,data){
44789 Publisher.Publish(action, data, this);
44790 });
44791 }
44792 }
44793
44794 StorytellingWidget.prototype = {
44795
44796 initWidget : function(data) {
44797 var storytellingWidget = this;
44798 var gui = storytellingWidget.gui;
44799
44800 storytellingWidget.datasets = data;
44801
44802 $(gui.storytellingContainer).empty();
44803
44804 var magneticLinkParam = "";
44805 var datasetIndex = 0;
44806 var linkCount = 1;
44807 $(storytellingWidget.datasets).each(function(){
44808 var dataset = this;
44809
44810 if (magneticLinkParam.length > 0)
44811 magneticLinkParam += "&";
44812
44813 var paragraph = $("<p></p>");
44814 paragraph.append(dataset.label);
44815 if (typeof dataset.url !== "undefined"){
44816 //TODO: makes only sense for KML or CSV URLs, so "type" of
44817 //URL should be preserved (in dataset).
44818 //startsWith and endsWith defined in SIMILE Ajax (string.js)
44819 var type="csv";
44820 if (typeof dataset.type !== "undefined")
44821 type = dataset.type;
44822 else {
44823 if (dataset.url.toLowerCase().endsWith("kml"))
44824 type = "kml";
44825 }
44826
44827 magneticLinkParam += type+linkCount+"=";
44828 linkCount++;
44829 magneticLinkParam += dataset.url;
44830
44831 var tableLinkDiv = document.createElement('a');
44832 tableLinkDiv.title = dataset.url;
44833 tableLinkDiv.href = dataset.url;
44834 tableLinkDiv.target = '_';
44835 tableLinkDiv.setAttribute('class', 'externalLink');
44836 paragraph.append(tableLinkDiv);
44837 } else {
44838 if (storytellingWidget.options.dariahStorage){
44839 var uploadToDARIAH = document.createElement('a');
44840 $(uploadToDARIAH).append("Upload to DARIAH Storage");
44841 uploadToDARIAH.title = "";
44842 uploadToDARIAH.href = dataset.url;
44843
44844 var localDatasetIndex = new Number(datasetIndex);
44845 $(uploadToDARIAH).click(function(){
44846 var csv = GeoTemConfig.createCSVfromDataset(localDatasetIndex);
44847 // taken from dariah.storage.js
44848 var storageURL = "http://ref.dariah.eu/storage/"
44849 $.ajax({
44850 url: storageURL,
44851 type: 'POST',
44852 contentType: 'text/csv',
44853 data: csv,
44854 success: function(data, status, xhr) {
44855 var location = xhr.getResponseHeader('Location');
44856 // the dariah storage id
44857 dsid = location.substring(location.lastIndexOf('/')+1);
44858
44859 //add URL to dataset
44860 storytellingWidget.datasets[localDatasetIndex].url = location;
44861 storytellingWidget.datasets[localDatasetIndex].type = "csv";
44862 //refresh list
44863 storytellingWidget.initWidget(storytellingWidget.datasets);
44864 },
44865 error: function (data, text, error) {
44866 alert('error creating new file in dariah storage because ' + text);
44867 console.log(data);
44868 console.log(text);
44869 console.log(error);
44870 }
44871 });
44872 //discard link click-event
44873 return(false);
44874 });
44875 paragraph.append(uploadToDARIAH);
44876 }
44877 // TODO: if layout is more usable, both options could be used ("else" removed)
44878 else if (storytellingWidget.options.localStorage){
44879 var saveToLocalStorage = document.createElement('a');
44880 $(saveToLocalStorage).append("Save to Local Storage");
44881 saveToLocalStorage.title = "";
44882 saveToLocalStorage.href = dataset.url;
44883
44884 var localDatasetIndex = new Number(datasetIndex);
44885 $(saveToLocalStorage).click(function(){
44886 var csv = GeoTemConfig.createCSVfromDataset(localDatasetIndex);
44887
44888 var storageName = "GeoBrowser_dataset_"+GeoTemConfig.datasets[localDatasetIndex].label;
44889 $.remember({
44890 name:storageName,
44891 value:csv
44892 });
44893
44894 //add URL to dataset
44895 storytellingWidget.datasets[localDatasetIndex].url = storageName;
44896 storytellingWidget.datasets[localDatasetIndex].type = "local";
44897 //refresh list
44898 storytellingWidget.initWidget(storytellingWidget.datasets);
44899
44900 //discard link click-event
44901 return(false);
44902 });
44903 paragraph.append(saveToLocalStorage);
44904 }
44905 }
44906
44907 $(gui.storytellingContainer).append(paragraph);
44908 datasetIndex++;
44909 });
44910
44911 this.datasetLink = magneticLinkParam;
44912 this.createLink();
44913 },
44914
44915 createLink : function() {
44916 $(this.gui.storytellingContainer).find('.magneticLink').remove();
44917
44918 var magneticLink = document.createElement('a');
44919 magneticLink.setAttribute('class', 'magneticLink');
44920 $(magneticLink).append("Magnetic Link");
44921 magneticLink.title = "Use this link to reload currently loaded (online) data.";
44922 magneticLink.href = "?"+this.datasetLink;
44923 var currentStatusParam = $.param(this.currentStatus);
44924 if (currentStatusParam.length > 0)
44925 magneticLink.href += "&currentStatus="+currentStatusParam;
44926 magneticLink.target = '_';
44927 $(this.gui.storytellingContainer).prepend(magneticLink);
44928 },
44929
44930 highlightChanged : function(objects) {
44931 },
44932
44933 selectionChanged : function(selection) {
44934 },
44935 };
44936 /*
44937 * LineOverlay.js
44938 *
44939 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44940 *
44941 * This library is free software; you can redistribute it and/or
44942 * modify it under the terms of the GNU Lesser General Public
44943 * License as published by the Free Software Foundation; either
44944 * version 3 of the License, or (at your option) any later version.
44945 *
44946 * This library is distributed in the hope that it will be useful,
44947 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44948 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44949 * Lesser General Public License for more details.
44950 *
44951 * You should have received a copy of the GNU Lesser General Public
44952 * License along with this library; if not, write to the Free Software
44953 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
44954 * MA 02110-1301 USA
44955 */
44956
44957 /**
44958 * @class LineOverlay
44959 * Implementation for an overlay showing lines between points
44960 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
44961 *
44962 * @param {HTML object} parent div to append the LineOverlay
44963 */
44964 function LineOverlay(parent) {
44965
44966 this.lineOverlay = this;
44967
44968 this.parent = parent;
44969 this.options = parent.options;
44970 this.attachedMapWidgets = parent.attachedMapWidgets;
44971
44972 this.overlays = [];
44973
44974 this.initialize();
44975 }
44976
44977 LineOverlay.prototype = {
44978
44979 initialize : function() {
44980 }
44981 };
44982 /*
44983 * LineOverlayConfig.js
44984 *
44985 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
44986 *
44987 * This library is free software; you can redistribute it and/or
44988 * modify it under the terms of the GNU Lesser General Public
44989 * License as published by the Free Software Foundation; either
44990 * version 3 of the License, or (at your option) any later version.
44991 *
44992 * This library is distributed in the hope that it will be useful,
44993 * but WITHOUT ANY WARRANTY; without even the implied warranty of
44994 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
44995 * Lesser General Public License for more details.
44996 *
44997 * You should have received a copy of the GNU Lesser General Public
44998 * License along with this library; if not, write to the Free Software
44999 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
45000 * MA 02110-1301 USA
45001 */
45002
45003 /**
45004 * @class LineOverlayConfig
45005 * LineOverlay Configuration File
45006 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
45007 */
45008 function LineOverlayConfig(options) {
45009 this.options = {
45010 showArrows : true,
45011 showLines : "both", //which directions will be shown: "both", "inbound", "outbound"
45012 onlyShowSelectedOrHighlighted : false, //only show lines in case of selection/highlight
45013 }
45014
45015 if ( typeof options != 'undefined') {
45016 $.extend(this.options, options);
45017 }
45018
45019 };
45020 /*
45021 * LineOverlayWidget.js
45022 *
45023 * Copyright (c) 2013, Sebastian Kruse. All rights reserved.
45024 *
45025 * This library is free software; you can redistribute it and/or
45026 * modify it under the terms of the GNU Lesser General Public
45027 * License as published by the Free Software Foundation; either
45028 * version 3 of the License, or (at your option) any later version.
45029 *
45030 * This library is distributed in the hope that it will be useful,
45031 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45033 * Lesser General Public License for more details.
45034 *
45035 * You should have received a copy of the GNU Lesser General Public
45036 * License along with this library; if not, write to the Free Software
45037 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
45038 * MA 02110-1301 USA
45039 */
45040
45041 //calculate angle between line and x-axis
45042 //credits: geometricnet (http://geometricnet.sourceforge.net/examples/directions.html)
45043 bearing = function(x1,y1,x2,y2) {
45044 b_x = 0;
45045 b_y = 1;
45046 a_x = x2 - x1;
45047 a_y = y2 - y1;
45048 angle_rad = Math.acos((a_x*b_x+a_y*b_y)/Math.sqrt(a_x*a_x+a_y*a_y)) ;
45049 angle = 360/(2*Math.PI)*angle_rad;
45050 if (a_x < 0) {
45051 return 360 - angle;
45052 } else {
45053 return angle;
45054 }
45055 };
45056
45057 /**
45058 * @class LineOverlayWidget
45059 * Implementation for the widget interactions of an overlay showing lines between points
45060 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de)
45061 *
45062 * @param {WidgetWrapper} core wrapper for interaction to other widgets
45063 * @param {JSON} options user specified configuration that overwrites options in OverlayloaderConfig.js
45064 */
45065 LineOverlayWidget = function (core, options) {
45066
45067 this.core = core;
45068 this.core.setWidget(this);
45069
45070 this.options = (new LineOverlayConfig(options)).options;
45071
45072 this.attachedMapWidgets = new Array();
45073
45074 this.lineOverlay = new LineOverlay(this);
45075 this.lines = [];
45076 this.multiLineFeature;
45077
45078 this.selected = [];
45079 }
45080
45081 /**
45082 * @param {Number} dataSet number of dataSet in dataSet array
45083 * @param {Number} objectID number of DataObject in objects array
45084 */
45085
45086 function Line(objectStart, objectEnd ) {
45087 this.objectStart = objectStart;
45088 this.objectEnd = objectEnd;
45089 }
45090
45091 LineOverlayWidget.prototype = {
45092
45093 initWidget : function() {
45094 var lineOverlayWidget = this;
45095 this.drawLines();
45096 },
45097
45098 highlightChanged : function(objects) {
45099 if( !GeoTemConfig.highlightEvents ){
45100 return;
45101 }
45102 this.drawLines(GeoTemConfig.mergeObjects(objects,this.selected));
45103 },
45104
45105 selectionChanged : function(selection) {
45106 if( !GeoTemConfig.selectionEvents ){
45107 return;
45108 }
45109 if (selection.valid())
45110 this.selected = selection.objects;
45111 else
45112 this.selected = [];
45113
45114 this.drawLines(this.selected);
45115 },
45116
45117 triggerHighlight : function(item) {
45118 },
45119
45120 tableSelection : function() {
45121 },
45122
45123 deselection : function() {
45124 },
45125
45126 filtering : function() {
45127 },
45128
45129 inverseFiltering : function() {
45130 },
45131
45132 triggerRefining : function() {
45133 },
45134
45135 reset : function() {
45136 },
45137
45138 //identical to the function in PieChartWidget
45139 //here cause widgets may be used independed of each other
45140 getElementData : function(dataObject, watchedColumn, selectionFunction) {
45141 var columnData;
45142 if (watchedColumn.indexOf("[") === -1){
45143 columnData = dataObject[watchedColumn];
45144 if (typeof columnData === "undefined"){
45145 columnData = dataObject.tableContent[watchedColumn];
45146 };
45147 } else {
45148 try {
45149 var columnName = watchedColumn.split("[")[0];
45150 var IndexAndAttribute = watchedColumn.split("[")[1];
45151 if (IndexAndAttribute.indexOf("]") != -1){
45152 var arrayIndex = IndexAndAttribute.split("]")[0];
45153 var attribute = IndexAndAttribute.split("]")[1];
45154
45155 if (typeof attribute === "undefined")
45156 columnData = dataObject[columnName][arrayIndex];
45157 else{
45158 attribute = attribute.split(".")[1];
45159 columnData = dataObject[columnName][arrayIndex][attribute];
45160 }
45161 }
45162 } catch(e) {
45163 if (typeof console !== undefined)
45164 console.error(e);
45165
45166 delete columnData;
45167 }
45168 }
45169
45170 if ( (typeof columnData !== "undefined") && (typeof selectionFunction !== "undefined") )
45171 columnData = selectionFunction(columnData);
45172
45173 return(columnData);
45174 },
45175
45176 matchColumns : function(dataSet1, columnName1, dataSet2, columnName2) {
45177 var lineOverlayWidget = this;
45178 lineOverlayWidget.lines;
45179 $(GeoTemConfig.datasets[dataSet1].objects).each(function(){
45180 var object1 = this;
45181 var data1 = lineOverlayWidget.getElementData(object1, columnName1);
45182 //split because there could be multiple comma separated values
45183 data1 = data1.split(",");
45184
45185 $(GeoTemConfig.datasets[dataSet2].objects).each(function(){
45186 var object2 = this;
45187 //avoid reflexive and double entries
45188 if ((columnName1 === columnName2)&&(dataSet1 === dataSet2)&&(object1.index<=object2.index))
45189 return;
45190 var data2 = lineOverlayWidget.getElementData(object2, columnName2);
45191 //split because there could be multiple comma separated values
45192 data2 = data2.split(",");
45193
45194 //check if at least one pair matches
45195 for(var i = 0; i < data1.length; i++ ){
45196 var firstVal = data1[i];
45197 if (data2.indexOf(firstVal) !== -1){
45198 lineOverlayWidget.lines.push(new Line(object1, object2));
45199 break;
45200 }
45201 }
45202 });
45203 });
45204 },
45205
45206 getXYofObject : function(cs,dataObject){
45207 //iterata over datasets
45208 var x,y;
45209 var found = false;
45210 $(cs).each(function(){
45211 //iterate over circles
45212 $(this).each(function(){
45213 var circle = this;
45214 //iterata over objects in this circle;
45215 var index = $.inArray(dataObject,circle.elements);
45216 if (index !== -1){
45217 x = circle.feature.geometry.x;
45218 y = circle.feature.geometry.y;
45219 found = true;
45220 return false;
45221 }
45222 });
45223 //break loop
45224 if (found === true)
45225 return false;
45226 });
45227
45228 return ({x:x,y:y});
45229 },
45230
45231 /**
45232 * @param {DataObjects[][]} objects set of objects to limit to
45233 */
45234 drawLines : function(objects) {
45235 var flatObjects = [];
45236 if ( (typeof objects !== "undefined") &&
45237 (objects instanceof Array) &&
45238 (objects.length > 0) ) {
45239 $(objects).each(function(){
45240 $.merge(flatObjects, this);
45241 });
45242 }
45243 var lineOverlayWidget = this;
45244
45245 $(lineOverlayWidget.attachedMapWidgets).each(function(){
45246 var mapWidget = this.mapWidget;
45247 var lineLayer = this.lineLayer;
45248
45249 var map = mapWidget.openlayersMap;
45250 var cs = mapWidget.mds.getObjectsByZoom();
45251
45252 mapWidget.openlayersMap.setLayerIndex(lineLayer, 99);
45253
45254 lineLayer.removeAllFeatures();
45255
45256 var lineElements = [];
45257
45258 var checkIfLineInPreset = function(){return false;};
45259 if (lineOverlayWidget.options.showLines === "inbound"){
45260 checkIfLineInPreset = function(objectStart,objectEnd,flatObjects){
45261 return ($.inArray(objectEnd, flatObjects) === -1);
45262 };
45263 } else if (lineOverlayWidget.options.showLines === "outbound"){
45264 checkIfLineInPreset = function(objectStart,objectEnd,flatObjects){
45265 return ($.inArray(objectStart, flatObjects) === -1);
45266 };
45267 } else /*if (lineOverlayWidget.options.showLines === "both")*/{
45268 checkIfLineInPreset = function(objectStart,objectEnd,flatObjects){
45269 return ( ($.inArray(objectStart, flatObjects) === -1) &&
45270 ($.inArray(objectEnd, flatObjects) === -1) );
45271 };
45272 }
45273
45274 $(lineOverlayWidget.lines).each(function(){
45275 var line = this;
45276
45277 if ((lineOverlayWidget.options.onlyShowSelectedOrHighlighted === true) || (flatObjects.length > 0)){
45278 //if objects are limited, check whether start or end are within
45279 if (checkIfLineInPreset(line.objectStart, line.objectEnd, flatObjects))
45280 return;
45281 }
45282 //get XY-val of start Object
45283 var xyStart = lineOverlayWidget.getXYofObject(cs, line.objectStart);
45284 //continue if no valid XY-coords where found
45285 if ( (typeof xyStart.x === "undefined") && (typeof xyStart.y === "undefined") )
45286 return;
45287 var xyEnd = lineOverlayWidget.getXYofObject(cs, line.objectEnd);
45288 //continue if no valid XY-coords where found
45289 if ( (typeof xyEnd.x === "undefined") && (typeof xyEnd.y === "undefined") )
45290 return;
45291
45292 //do not draw 0-length lines (from same circle)
45293 if ( (xyStart.x === xyEnd.x) && (xyStart.y === xyEnd.y) )
45294 return;
45295
45296 var points = new Array(
45297 new OpenLayers.Geometry.Point(xyStart.x, xyStart.y),
45298 new OpenLayers.Geometry.Point(xyEnd.x, xyEnd.y)
45299 );
45300
45301 var line = new OpenLayers.Geometry.LineString(points);
45302
45303 //Only draw each line once. Unfortunately this check is faster
45304 //than drawing multiple lines.
45305 var found = false;
45306 $(lineElements).each(function(){
45307 var checkLine = this.line;
45308 if (( (checkLine.components[0].x === line.components[0].x) &&
45309 (checkLine.components[0].y === line.components[0].y) &&
45310 (checkLine.components[1].x === line.components[1].x) &&
45311 (checkLine.components[1].y === line.components[1].y) ) ||
45312 // if lines are "directional" (arrows) the opposite one isn't the same anymore!
45313 ( (lineOverlayWidget.options.showArrows === false) &&
45314 (checkLine.components[0].x === line.components[1].x) &&
45315 (checkLine.components[0].y === line.components[1].y) &&
45316 (checkLine.components[1].x === line.components[0].x) &&
45317 (checkLine.components[1].y === line.components[0].y) ) ){
45318 found = true;
45319 //increase width of this line
45320 this.width++;
45321 //and don't draw it again
45322 return false;
45323 }
45324 });
45325
45326 if (found === true)
45327 return;
45328
45329 lineElements.push({line:line,width:1});
45330 });
45331
45332 $(lineElements).each(function(){
45333 var line = this.line;
45334 var width = this.width;
45335
45336 if (lineOverlayWidget.options.showArrows === true){
45337 var xyStart = line.components[0];
45338 var xyEnd = line.components[1];
45339 var arrowFeature = new OpenLayers.Feature.Vector(
45340 new OpenLayers.Geometry.Point(xyEnd.x-((xyEnd.x-xyStart.x)*0.03), xyEnd.y-((xyEnd.y-xyStart.y)*0.03)),
45341 {
45342 type: "triangle",
45343 angle: bearing(xyStart.x,xyStart.y,xyEnd.x,xyEnd.y),
45344 width: width+1
45345 }
45346 );
45347 lineLayer.addFeatures(arrowFeature);
45348 }
45349
45350 var lineFeature = new OpenLayers.Feature.Vector(line,{width:width});
45351 lineLayer.addFeatures(lineFeature);
45352 });
45353 });
45354 },
45355
45356 attachMapWidget : function(mapWidget) {
45357 var styles = new OpenLayers.StyleMap({
45358 "default": {
45359 graphicName: "${type}",
45360 rotation: "${angle}",
45361 pointRadius: "${width}",
45362 strokeColor: '#0000ff',
45363 strokeOpacity: 0.5,
45364 strokeWidth: "${width}",
45365 fillOpacity: 1
45366 }
45367 });
45368
45369 var lineOverlayWidget = this;
45370 var lineLayer = new OpenLayers.Layer.Vector("Line Layer", {
45371 styleMap: styles,
45372 isBaseLayer:false
45373 });
45374 mapWidget.openlayersMap.addLayer(lineLayer);
45375 mapWidget.openlayersMap.setLayerIndex(lineLayer, 99);
45376 this.attachedMapWidgets.push({mapWidget:mapWidget,lineLayer:lineLayer});
45377 //register zoom event
45378 mapWidget.openlayersMap.events.register("zoomend", lineOverlayWidget, function(){
45379 this.drawLines(this.selected);
45380 });
45381 }
45382 };
45383 /*
45384 * DataObject.js
45385 *
45386 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
45387 *
45388 * This library is free software; you can redistribute it and/or
45389 * modify it under the terms of the GNU Lesser General Public
45390 * License as published by the Free Software Foundation; either
45391 * version 3 of the License, or (at your option) any later version.
45392 *
45393 * This library is distributed in the hope that it will be useful,
45394 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45395 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45396 * Lesser General Public License for more details.
45397 *
45398 * You should have received a copy of the GNU Lesser General Public
45399 * License along with this library; if not, write to the Free Software
45400 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
45401 * MA 02110-1301 USA
45402 */
45403
45404 /**
45405 * @class DataObject
45406 * GeoTemCo's data object class
45407 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
45408 * @release 1.0
45409 * @release date: 2012-07-27
45410 * @version date: 2012-07-27
45411 *
45412 * @param {String} name name of the data object
45413 * @param {String} description description of the data object
45414 * @param {JSON} locations a list of locations with longitude, latitide and place name
45415 * @param {JSON} dates a list of dates
45416 * @param {float} lon longitude value of the given place
45417 * @param {float} lat latitude value of the given place
45418 * @param {Date} timeStart start time of the data object
45419 * @param {Date} timeEnd end time of the data object
45420 * @param {int} granularity granularity of the given time
45421 * @param {int} weight weight of the time object
45422 * @param {Openlayers.Projection} projection of the coordinates (optional)
45423 */
45424
45425 DataObject = function(name, description, locations, dates, weight, tableContent, projection) {
45426
45427 this.name = $.trim(name);
45428 this.description = $.trim(description);
45429 this.weight = weight;
45430 this.tableContent = new Object();
45431 var objectTableContent = this.tableContent;
45432 for(key in tableContent){
45433 value = tableContent[key];
45434 objectTableContent[$.trim(key)]=$.trim(value);
45435 }
45436
45437 this.percentage = 0;
45438 this.setPercentage = function(percentage) {
45439 this.percentage = percentage;
45440 }
45441
45442 this.locations = [];
45443 var objectLocations = this.locations;
45444 $(locations).each(function(){
45445 objectLocations.push({
45446 latitude:this.latitude,
45447 longitude:this.longitude,
45448 place:$.trim(this.place)
45449 });
45450 });
45451
45452 //Check if locations are valid
45453 if (!(projection instanceof OpenLayers.Projection)){
45454 //per default GeoTemCo uses WGS84 (-90<=lat<=90, -180<=lon<=180)
45455 projection = new OpenLayers.Projection("EPSG:4326");
45456 }
45457 this.projection = projection;
45458
45459 var tempLocations = [];
45460 if (typeof this.locations !== "undefined"){
45461 $(this.locations).each(function(){
45462 //EPSG:4326 === WGS84
45463 this.latitude = parseFloat(this.latitude);
45464 this.longitude = parseFloat(this.longitude);
45465 if (projection.getCode() === "EPSG:4326"){
45466 if ( (typeof this.latitude === "number") &&
45467 (this.latitude>=-90) &&
45468 (this.latitude<=90) &&
45469 (typeof this.longitude === "number") &&
45470 (this.longitude>=-180) &&
45471 (this.longitude<=180) )
45472 tempLocations.push(this);
45473 else{
45474 if ((GeoTemConfig.debug)&&(typeof console !== undefined)){
45475 console.error("Object " + name + " has no valid coordinate. ("+this.latitude+","+this.longitude+")");
45476 }
45477 }
45478
45479 //solve lat=-90 bug
45480 if( this.longitude == 180 ){
45481 this.longitude = 179.999;
45482 }
45483 if( this.longitude == -180 ){
45484 this.longitude = -179.999;
45485 }
45486 if( this.latitude == 90 ){
45487 this.latitude = 89.999;
45488 }
45489 if( this.latitude == -90 ){
45490 this.latitude = -89.999;
45491 }
45492 }
45493 });
45494 this.locations = tempLocations;
45495 }
45496
45497 this.isGeospatial = false;
45498 if ((typeof this.locations !== "undefined") && (this.locations.length > 0)) {
45499 this.isGeospatial = true;
45500 }
45501
45502 this.placeDetails = [];
45503 for (var i = 0; i < this.locations.length; i++) {
45504 this.placeDetails.push(this.locations[i].place.split("/"));
45505 }
45506
45507 this.getLatitude = function(locationId) {
45508 return this.locations[locationId].latitude;
45509 }
45510
45511 this.getLongitude = function(locationId) {
45512 return this.locations[locationId].longitude;
45513 }
45514
45515 this.getPlace = function(locationId, level) {
45516 if (level >= this.placeDetails[locationId].length) {
45517 return this.placeDetails[locationId][this.placeDetails[locationId].length - 1];
45518 }
45519 return this.placeDetails[locationId][level];
45520 }
45521
45522 this.dates = dates;
45523 this.isTemporal = false;
45524 if ((typeof this.dates !== "undefined") && (this.dates.length > 0)) {
45525 this.isTemporal = true;
45526 //test if we already have date "objects" or if we should parse the dates
45527 for (var i = 0; i < this.dates.length; i++){
45528 if (typeof this.dates[i] === "string"){
45529 var date = GeoTemConfig.getTimeData(this.dates[i]);
45530 //check whether we got valid dates
45531 if ((typeof date !== "undefined")&&(date != null)){
45532 this.dates[i] = date;
45533 } else {
45534 //at least one date is invalid, so this dataObject has
45535 //no valid date information and is therefor not "temporal"
45536 this.isTemporal = false;
45537 break;
45538 }
45539 }
45540 }
45541 }
45542
45543 //TODO: allow more than one timespan (as with dates/places)
45544 this.isFuzzyTemporal = false;
45545 if (this.isTemporal) {
45546 this.isTemporal = false;
45547 this.isFuzzyTemporal = true;
45548
45549 var date = this.dates[0].date;
45550 var granularity = this.dates[0].granularity;
45551
45552 this.TimeSpanGranularity = granularity;
45553
45554 if (granularity === SimileAjax.DateTime.YEAR){
45555 this.TimeSpanBegin = moment(date).startOf("year");
45556 this.TimeSpanEnd = moment(date).endOf("year");
45557 } else if (granularity === SimileAjax.DateTime.MONTH){
45558 this.TimeSpanBegin = moment(date).startOf("month");
45559 this.TimeSpanEnd = moment(date).endOf("month");
45560 } else if (granularity === SimileAjax.DateTime.DAY){
45561 this.TimeSpanBegin = moment(date).startOf("day");
45562 this.TimeSpanEnd = moment(date).endOf("day");
45563 } else if (granularity === SimileAjax.DateTime.HOUR){
45564 this.TimeSpanBegin = moment(date).startOf("hour");
45565 this.TimeSpanEnd = moment(date).endOf("hour");
45566 } else if (granularity === SimileAjax.DateTime.MINUTE){
45567 this.TimeSpanBegin = moment(date).startOf("minute");
45568 this.TimeSpanEnd = moment(date).endOf("minute");
45569 } else if (granularity === SimileAjax.DateTime.SECOND){
45570 this.TimeSpanBegin = moment(date).startOf("second");
45571 this.TimeSpanEnd = moment(date).endOf("second");
45572 } else if (granularity === SimileAjax.DateTime.MILLISECOND){
45573 //this is a "real" exact time
45574 this.isTemporal = true;
45575 this.isFuzzyTemporal = false;
45576 }
45577 } else if ( (typeof this.tableContent["TimeSpan:begin"] !== "undefined") &&
45578 (typeof this.tableContent["TimeSpan:end"] !== "undefined") ){
45579 //parse according to ISO 8601
45580 //don't use the default "cross browser support" from moment.js
45581 //cause it won't work correctly with negative years
45582 var formats = [ "YYYYYY",
45583 "YYYYYY-MM",
45584 "YYYYYY-MM-DD",
45585 "YYYYYY-MM-DDTHH",
45586 "YYYYYY-MM-DDTHH:mm",
45587 "YYYYYY-MM-DDTHH:mm:ss",
45588 "YYYYYY-MM-DDTHH:mm:ss.SSS"
45589 ];
45590 this.TimeSpanBegin = moment(this.tableContent["TimeSpan:begin"],formats.slice());
45591 this.TimeSpanEnd = moment(this.tableContent["TimeSpan:end"],formats.slice());
45592 if ((this.TimeSpanBegin instanceof Object) && this.TimeSpanBegin.isValid() &&
45593 (this.TimeSpanEnd instanceof Object) && this.TimeSpanEnd.isValid()){
45594 //check whether dates are correctly sorted
45595 if (this.TimeSpanBegin>this.TimeSpanEnd){
45596 //dates are in the wrong order
45597 if ((GeoTemConfig.debug)&&(typeof console !== undefined))
45598 console.error("Object " + this.name + " has wrong fuzzy dating (twisted start/end?).");
45599
45600 } else {
45601 var timeSpanBeginGranularity = formats.indexOf(this.TimeSpanBegin._f);
45602 var timeSpanEndGranularity = formats.indexOf(this.TimeSpanEnd._f);
45603 var timeSpanGranularity = Math.max( timeSpanBeginGranularity,
45604 timeSpanEndGranularity );
45605
45606 //set granularity according to formats above
45607 if (timeSpanGranularity === 0){
45608 this.TimeSpanGranularity = SimileAjax.DateTime.YEAR;
45609 } else if (timeSpanGranularity === 1){
45610 this.TimeSpanGranularity = SimileAjax.DateTime.MONTH;
45611 } else if (timeSpanGranularity === 2){
45612 this.TimeSpanGranularity = SimileAjax.DateTime.DAY;
45613 } else if (timeSpanGranularity === 3){
45614 this.TimeSpanGranularity = SimileAjax.DateTime.HOUR;
45615 } else if (timeSpanGranularity === 4){
45616 this.TimeSpanGranularity = SimileAjax.DateTime.MINUTE;
45617 } else if (timeSpanGranularity === 5){
45618 this.TimeSpanGranularity = SimileAjax.DateTime.SECOND;
45619 } else if (timeSpanGranularity === 6){
45620 this.TimeSpanGranularity = SimileAjax.DateTime.MILLISECOND;
45621 }
45622
45623 if (timeSpanBeginGranularity === 0){
45624 this.TimeSpanBeginGranularity = SimileAjax.DateTime.YEAR;
45625 } else if (timeSpanBeginGranularity === 1){
45626 this.TimeSpanBeginGranularity = SimileAjax.DateTime.MONTH;
45627 } else if (timeSpanBeginGranularity === 2){
45628 this.TimeSpanBeginGranularity = SimileAjax.DateTime.DAY;
45629 } else if (timeSpanBeginGranularity === 3){
45630 this.TimeSpanBeginGranularity = SimileAjax.DateTime.HOUR;
45631 } else if (timeSpanBeginGranularity === 4){
45632 this.TimeSpanBeginGranularity = SimileAjax.DateTime.MINUTE;
45633 } else if (timeSpanBeginGranularity === 5){
45634 this.TimeSpanBeginGranularity = SimileAjax.DateTime.SECOND;
45635 } else if (timeSpanBeginGranularity === 6){
45636 this.TimeSpanBeginGranularity = SimileAjax.DateTime.MILLISECOND;
45637 }
45638
45639 if (timeSpanEndGranularity === 0){
45640 this.TimeSpanEndGranularity = SimileAjax.DateTime.YEAR;
45641 } else if (timeSpanEndGranularity === 1){
45642 this.TimeSpanEndGranularity = SimileAjax.DateTime.MONTH;
45643 } else if (timeSpanEndGranularity === 2){
45644 this.TimeSpanEndGranularity = SimileAjax.DateTime.DAY;
45645 } else if (timeSpanEndGranularity === 3){
45646 this.TimeSpanEndGranularity = SimileAjax.DateTime.HOUR;
45647 } else if (timeSpanEndGranularity === 4){
45648 this.TimeSpanEndGranularity = SimileAjax.DateTime.MINUTE;
45649 } else if (timeSpanEndGranularity === 5){
45650 this.TimeSpanEndGranularity = SimileAjax.DateTime.SECOND;
45651 } else if (timeSpanEndGranularity === 6){
45652 this.TimeSpanEndGranularity = SimileAjax.DateTime.MILLISECOND;
45653 }
45654
45655 if (this.TimeSpanEnd.year()-this.TimeSpanBegin.year() >= 1000)
45656 this.TimeSpanGranularity = SimileAjax.DateTime.MILLENNIUM;
45657 else if (this.TimeSpanEnd.year()-this.TimeSpanBegin.year() >= 100)
45658 this.TimeSpanGranularity = SimileAjax.DateTime.CENTURY;
45659 else if (this.TimeSpanEnd.year()-this.TimeSpanBegin.year() >= 10)
45660 this.TimeSpanGranularity = SimileAjax.DateTime.DECADE;
45661
45662 //also set upper bounds according to granularity
45663 //(lower bound is already correct)
45664 if (timeSpanEndGranularity === 0){
45665 this.TimeSpanEnd.endOf("year");
45666 } else if (timeSpanEndGranularity === 1){
45667 this.TimeSpanEnd.endOf("month");
45668 } else if (timeSpanEndGranularity === 2){
45669 this.TimeSpanEnd.endOf("day");
45670 } else if (timeSpanEndGranularity === 3){
45671 this.TimeSpanEnd.endOf("hour");
45672 } else if (timeSpanEndGranularity === 4){
45673 this.TimeSpanEnd.endOf("minute");
45674 } else if (timeSpanEndGranularity === 5){
45675 this.TimeSpanEnd.endOf("second");
45676 } else if (timeSpanEndGranularity === 6){
45677 //has max accuracy, so no change needed
45678 }
45679
45680 this.isFuzzyTemporal = true;
45681 }
45682 }
45683 }
45684
45685
45686 this.getDate = function(dateId) {
45687 return this.dates[dateId].date;
45688 }
45689
45690 this.getTimeGranularity = function(dateId) {
45691 return this.dates[dateId].granularity;
45692 }
45693
45694 this.setIndex = function(index) {
45695 this.index = index;
45696 }
45697
45698 this.getTimeString = function() {
45699 if (this.timeStart != this.timeEnd) {
45700 return (SimileAjax.DateTime.getTimeString(this.granularity, this.timeStart) + " - " + SimileAjax.DateTime.getTimeString(this.granularity, this.timeEnd));
45701 } else {
45702 return SimileAjax.DateTime.getTimeString(this.granularity, this.timeStart) + "";
45703 }
45704 };
45705
45706 this.contains = function(text) {
45707 var allCombined = this.name + " " + this.description + " " + this.weight + " ";
45708
45709 $.each(this.dates, function(key, value){
45710 $.each(value, function(){
45711 allCombined += this + " ";
45712 });
45713 });
45714
45715 $.each(this.locations, function(key, value){
45716 $.each(value, function(){
45717 allCombined += this + " ";
45718 });
45719 });
45720
45721 $.each(this.tableContent, function(key, value){
45722 allCombined += value + " ";
45723 });
45724
45725 return (allCombined.indexOf(text) != -1);
45726 };
45727
45728 this.hasColorInformation = false;
45729
45730 this.setColor = function(r0,g0,b0,r1,g1,b1) {
45731 this.hasColorInformation = true;
45732
45733 this.color = new Object();
45734 this.color.r0 = r0;
45735 this.color.g0 = g0;
45736 this.color.b0 = b0;
45737 this.color.r1 = r1;
45738 this.color.g1 = g1;
45739 this.color.b1 = b1;
45740 };
45741
45742 this.getColor = function() {
45743 if (!this.hasColorInformation)
45744 return;
45745
45746 color = new Object();
45747 color.r0 = this.r0;
45748 color.g0 = this.g0;
45749 color.b0 = this.b0;
45750 color.r1 = this.r1;
45751 color.g1 = this.g1;
45752 color.b1 = this.b1;
45753
45754 return color;
45755 };
45756
45757 Publisher.Publish('dataobjectAfterCreation', this);
45758 };
45759
45760 /*
45761 * Dataset.js
45762 *
45763 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
45764 *
45765 * This library is free software; you can redistribute it and/or
45766 * modify it under the terms of the GNU Lesser General Public
45767 * License as published by the Free Software Foundation; either
45768 * version 3 of the License, or (at your option) any later version.
45769 *
45770 * This library is distributed in the hope that it will be useful,
45771 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45772 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45773 * Lesser General Public License for more details.
45774 *
45775 * You should have received a copy of the GNU Lesser General Public
45776 * License along with this library; if not, write to the Free Software
45777 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
45778 * MA 02110-1301 USA
45779 */
45780
45781 /**
45782 * @class Dataset
45783 * GeoTemCo's Dataset class
45784 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
45785 * @release 1.0
45786 * @release date: 2012-07-27
45787 * @version date: 2012-07-27
45788 *
45789 * @param {Array} objects data item arrays from different datasets
45790 * @param {String} label label for the datasets
45791 */
45792 Dataset = function(objects, label, url, type) {
45793
45794 this.objects = objects;
45795 this.label = label;
45796 this.url = url;
45797 this.type = type;
45798
45799 this.color;
45800
45801 //if the user can change shapes, every dataset needs a default shape
45802 if (GeoTemConfig.allowUserShapeAndColorChange){
45803 this.graphic={
45804 shape: "circle",
45805 rotation: 0
45806 }
45807 }
45808
45809 Publisher.Publish('datasetAfterCreation', this);
45810 }
45811 /*
45812 * TimeDataSource.js
45813 *
45814 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
45815 *
45816 * This library is free software; you can redistribute it and/or
45817 * modify it under the terms of the GNU Lesser General Public
45818 * License as published by the Free Software Foundation; either
45819 * version 3 of the License, or (at your option) any later version.
45820 *
45821 * This library is distributed in the hope that it will be useful,
45822 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45823 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45824 * Lesser General Public License for more details.
45825 *
45826 * You should have received a copy of the GNU Lesser General Public
45827 * License along with this library; if not, write to the Free Software
45828 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
45829 * MA 02110-1301 USA
45830 */
45831
45832 /**
45833 * @class TimeDataSource, TimeSlice, TimeStack
45834 * implementation for aggregation of time items
45835 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
45836 * @release 1.0
45837 * @release date: 2012-07-27
45838 * @version date: 2012-07-27
45839 *
45840 * @param {JSON} options time configuration
45841 */
45842 function TimeDataSource(options) {
45843
45844 this.options = options;
45845 this.timeSlices = [];
45846 this.unit
45847 this.minDate
45848 this.maxDate
45849 this.eventSources
45850 this.events
45851 this.leftSlice
45852 this.rightSlice
45853
45854 this.hashMapping
45855
45856 };
45857
45858 TimeDataSource.prototype = {
45859
45860 findTimeUnits : function(granularity, timeUnit, pixels) {
45861
45862 var time = SimileAjax.DateTime;
45863 this.availableUnits = [];
45864 var givenUnits = SimileAjax.DateTime.gregorianUnitLengths;
45865 for (var i = 0; i < givenUnits.length; i++) {
45866 if (granularity > i) {
45867 continue;
45868 }
45869 var slices = 0;
45870 var t = new Date(this.minDate.getTime());
45871 do {
45872 time.roundDownToInterval(t, i, undefined, 1, 0);
45873 slices++;
45874 time.incrementByInterval(t, i, undefined);
45875 } while( t.getTime() <= this.maxDate.getTime() && slices < pixels+2 );
45876 if (slices > 0 && slices <= pixels) {
45877 this.availableUnits.push({
45878 unit : i,
45879 slices : slices,
45880 label : SimileAjax.DateTime.Strings[GeoTemConfig.language][i]
45881 });
45882 }
45883 }
45884 var unitDiff200 = pixels + 1;
45885 for (var i = 0; i < this.availableUnits.length; i++) {
45886 var diff = Math.abs(this.availableUnits[i].slices - 200);
45887 if (diff < unitDiff200) {
45888 unitDiff200 = diff;
45889 this.unit = this.availableUnits[i].unit;
45890 }
45891 }
45892
45893 },
45894
45895 getUnitIndex : function() {
45896 for (var i = 0; i < this.availableUnits.length; i++) {
45897 if (this.unit == this.availableUnits[i].unit) {
45898 return i;
45899 }
45900 }
45901 return 0;
45902 },
45903
45904 setTimeUnit : function(unit) {
45905 this.unit = unit;
45906 this.initializeSlices();
45907 },
45908
45909 /**
45910 * initializes the TimeDataSource
45911 * @param {Timeplot.ColumnSource[]} dataSources the column sources corresponding to the data sets
45912 * @param {Timeplot.DefaultEventSource[]} eventSources the event sources corresponding to the column sources
45913 * @param {TimeObject[][]} timeObjects an array of time objects of different sets
45914 * @param {SimileAjax.DateTime} granularity the time granularity of the given data
45915 */
45916 initialize : function(dataSources, eventSources, timeObjects, granularity, timeUnit, pixels) {
45917
45918 this.dataSources = dataSources;
45919 this.eventSources = eventSources;
45920 this.timeObjects = timeObjects;
45921
45922 this.minDate = undefined;
45923 this.maxDate = undefined;
45924 this.hashMapping = [];
45925 this.projHashMapping = [];
45926
45927 for (var i = 0; i < timeObjects.length; i++) {
45928 this.hashMapping.push([]);
45929 this.projHashMapping.push([]);
45930 for (var j = 0; j < timeObjects[i].length; j++) {
45931 var o = timeObjects[i][j];
45932 if (o.isTemporal) {
45933 var g = o.dates[this.options.timeIndex].granularity;
45934 //o.getTimeGranularity(this.options.timeIndex);
45935 if (g == null) {
45936 continue;
45937 }
45938 var time = o.dates[this.options.timeIndex].date;
45939 //o.getDate(this.options.timeIndex);
45940 if (this.minDate == undefined || time.getTime() < this.minDate.getTime()) {
45941 this.minDate = time;
45942 }
45943 if (this.maxDate == undefined || time.getTime() > this.maxDate.getTime()) {
45944 this.maxDate = time;
45945 }
45946 }
45947 }
45948 }
45949
45950 if (this.minDate == undefined) {
45951 this.minDate = this.options.defaultMinDate;
45952 this.maxDate = this.options.defaultMaxDate;
45953 }
45954
45955 this.findTimeUnits(granularity, timeUnit, pixels);
45956 this.initializeSlices();
45957
45958 },
45959
45960 initializeSlices : function() {
45961 for (var i = 0; i < this.dataSources.length; i++) {
45962 this.dataSources[i]._range = {
45963 earliestDate : null,
45964 latestDate : null,
45965 min : 0,
45966 max : 0
45967 };
45968 }
45969 this.timeSlices = [];
45970 var time = SimileAjax.DateTime;
45971 var t = new Date(this.minDate.getTime() - 0.9 * time.gregorianUnitLengths[this.unit]);
45972 do {
45973 time.roundDownToInterval(t, this.unit, undefined, 1, 0);
45974 var slice = new TimeSlice(SimileAjax.NativeDateUnit.cloneValue(t), this.timeObjects.length, this.dataSources.length);
45975 this.timeSlices.push(slice);
45976 time.incrementByInterval(t, this.unit, undefined);
45977 } while (t.getTime() <= this.maxDate.getTime() + 1.1 * time.gregorianUnitLengths[this.unit]);
45978
45979 for (var i = 0; i < this.timeObjects.length; i++) {
45980 var projId = i;
45981 if( this.dataSources.length == 1 ){
45982 projId = 0;
45983 }
45984 for (var j = 0; j < this.timeObjects[i].length; j++) {
45985 var o = this.timeObjects[i][j];
45986 if (o.isTemporal) {
45987 var date = o.dates[this.options.timeIndex].date;
45988 //o.getDate(this.options.timeIndex);
45989 for (var k = 0; k < this.timeSlices.length - 1; k++) {
45990 var t1 = this.timeSlices[k].date.getTime();
45991 var t2 = this.timeSlices[k + 1].date.getTime();
45992 var stack = null, projStack = null;
45993 if (date >= t1 && date < t2) {
45994 stack = this.timeSlices[k].getStack(i);
45995 projStack = this.timeSlices[k].getProjStack(projId);
45996 }
45997 if (k == this.timeSlices.length - 2 && date >= t2) {
45998 stack = this.timeSlices[k + 1].getStack(i);
45999 projStack = this.timeSlices[k + 1].getProjStack(projId);
46000 }
46001 if (stack != null) {
46002 stack.addObject(o);
46003 projStack.addObject(o);
46004 this.hashMapping[i][o.index] = stack;
46005 this.projHashMapping[i][o.index] = projStack;
46006 break;
46007 }
46008 }
46009 }
46010 }
46011 }
46012
46013 this.events = [];
46014 for (var i = 0; i < this.eventSources.length; i++) {
46015 var eventSet = [];
46016 for (var j = 0; j < this.timeSlices.length; j++) {
46017 var value = new Array("" + this.timeSlices[j].projStacks[i].value);
46018 eventSet.push({
46019 date : this.timeSlices[j].date,
46020 value : value
46021 });
46022 }
46023 this.eventSources[i].loadData(eventSet);
46024 this.events.push(eventSet);
46025 }
46026
46027 this.leftSlice = 0;
46028 this.rightSlice = this.timeSlices.length - 1;
46029
46030 },
46031
46032 getSliceNumber : function() {
46033 return this.timeSlices.length;
46034 },
46035
46036 /**
46037 * computes the slice index corresponding to a given time
46038 * @param {Date} time the given time
46039 * @return the corresponding slice index
46040 */
46041 getSliceIndex : function(time) {
46042 for (var i = 0; i < this.timeSlices.length; i++) {
46043 if (time == this.timeSlices[i].date) {
46044 return i;
46045 }
46046 }
46047 },
46048
46049 /**
46050 * returns the time of a specific time slice
46051 * @param {int} time the given slice index
46052 * @return the corresponding slice date
46053 */
46054 getSliceTime : function(index) {
46055 return this.timeSlices[index].date;
46056 },
46057
46058 /**
46059 * shifts the actual zoomed range
46060 * @param {int} delta the value to shift (negative for left shift, positive for right shift)
46061 * @return boolean value, if the range could be shifted
46062 */
46063 setShift : function(delta) {
46064 if (delta == 1 && this.leftSlice != 0) {
46065 this.leftSlice--;
46066 this.rightSlice--;
46067 return true;
46068 } else if (delta == -1 && this.rightSlice != this.timeSlices.length - 1) {
46069 this.leftSlice++;
46070 this.rightSlice++;
46071 return true;
46072 } else {
46073 return false;
46074 }
46075 },
46076
46077 /**
46078 * zooms the actual range
46079 * @param {int} delta the value to zoom (negative for zoom out, positive for zoom in)
46080 * @param {Date} time the corresponding time of the actual mouse position on the plot
46081 * @param {Date} leftTime the time of the left border of a selected timerange or null
46082 * @param {Date} rightTime the time of the right border of a selected timerange or null
46083 * @return boolean value, if the range could be zoomed
46084 */
46085 setZoom : function(delta, time, leftTime, rightTime) {
46086 var n1 = 0;
46087 var n2 = 0;
46088 var m = -1;
46089 if (delta > 0) {
46090 m = 1;
46091 if (leftTime != null) {
46092 n1 = this.getSliceIndex(leftTime) - this.leftSlice;
46093 n2 = this.rightSlice - this.getSliceIndex(rightTime);
46094 } else {
46095 slice = this.getSliceIndex(time);
46096 if (slice == this.leftSlice || slice == this.rightSlice) {
46097 return;
46098 }
46099 n1 = slice - 1 - this.leftSlice;
46100 n2 = this.rightSlice - slice - 1;
46101 }
46102 } else if (delta < 0) {
46103
46104 n1 = this.leftSlice;
46105 n2 = this.timeSlices.length - 1 - this.rightSlice;
46106 }
46107
46108 var zoomSlices = 2 * delta;
46109 if (Math.abs(n1 + n2) < Math.abs(zoomSlices)) {
46110 zoomSlices = n1 + n2;
46111 }
46112
46113 if (n1 + n2 == 0) {
46114 return false;
46115 }
46116
46117 var m1 = Math.round(n1 / (n1 + n2) * zoomSlices);
46118 var m2 = zoomSlices - m1;
46119
46120 this.leftSlice += m1;
46121 this.rightSlice -= m2;
46122
46123 return true;
46124 },
46125
46126 /**
46127 * resets the plots by loading data of actual zoomed range
46128 */
46129 reset : function(timeGeometry) {
46130 for (var i = 0; i < this.eventSources.length; i++) {
46131 this.eventSources[i].loadData(this.events[i].slice(this.leftSlice, this.rightSlice + 1));
46132 if (i + 1 < this.eventSources.length) {
46133 timeGeometry._earliestDate = null;
46134 timeGeometry._latestDate = null;
46135 }
46136
46137 }
46138 },
46139
46140 /**
46141 * Getter for actual zoom
46142 * @return actual zoom value
46143 */
46144 getZoom : function() {
46145 if (this.timeSlices == undefined) {
46146 return 0;
46147 }
46148 return Math.round((this.timeSlices.length - 3) / 2) - Math.round((this.rightSlice - this.leftSlice - 2) / 2);
46149 },
46150
46151 /**
46152 * Getter for date of the first timeslice
46153 * @return date of the first timeslice
46154 */
46155 earliest : function() {
46156 return this.timeSlices[0].date;
46157 },
46158
46159 /**
46160 * Getter for date of the last timeslice
46161 * @return date of the last timeslice
46162 */
46163 latest : function() {
46164 return this.timeSlices[this.timeSlices.length - 1].date;
46165 },
46166
46167 setOverlay : function(timeObjects) {
46168 for (var i = 0; i < this.timeSlices.length; i++) {
46169 this.timeSlices[i].reset();
46170 }
46171 for (var j in timeObjects ) {
46172 for (var k in timeObjects[j] ) {
46173 var o = timeObjects[j][k];
46174 if (o.isTemporal) {
46175 if (o.getTimeGranularity(this.options.timeIndex) == null) {
46176 continue;
46177 }
46178 this.hashMapping[j][o.index].overlay += o.weight;
46179 this.projHashMapping[j][o.index].overlay += o.weight;
46180 }
46181 }
46182 }
46183 },
46184
46185 size : function() {
46186 if (this.timeSlices.length == 0) {
46187 return 0;
46188 }
46189 return this.timeSlices[0].stacks.length;
46190 }
46191 };
46192
46193 /**
46194 * small class that represents a time slice of the actual timeplot.
46195 * it has a specific date and contains its corrsponding data objects as well
46196 */
46197 function TimeSlice(date, rows, projRows) {
46198
46199 this.date = date;
46200 this.selected = false;
46201
46202 this.stacks = [];
46203 this.projStacks = [];
46204 for (var i = 0; i < rows; i++) {
46205 this.stacks.push(new TimeStack());
46206 }
46207 for (var i = 0; i < projRows; i++) {
46208 this.projStacks.push(new TimeStack());
46209 }
46210
46211 this.getStack = function(row) {
46212 return this.stacks[row];
46213 };
46214
46215 this.getProjStack = function(row) {
46216 return this.projStacks[row];
46217 };
46218
46219 this.reset = function() {
46220 for (var i in this.projStacks ) {
46221 this.stacks[i].overlay = 0;
46222 this.projStacks[i].overlay = 0;
46223 }
46224 };
46225
46226 this.overlay = function() {
46227 var value = 0;
46228 for (var i in this.projStacks ) {
46229 if (this.projStacks[i].overlay > value) {
46230 value = this.projStacks[i].overlay;
46231 }
46232 }
46233 return value;
46234 };
46235
46236 };
46237
46238 /**
46239 * small class that represents a stack for a time slice which
46240 * holds items for different datasets for the specific time range
46241 */
46242 function TimeStack() {
46243
46244 this.overlay = 0;
46245 this.value = 0;
46246 this.elements = [];
46247
46248 this.addObject = function(object) {
46249 this.elements.push(object);
46250 this.value += object.weight;
46251 };
46252
46253 };
46254 /*
46255 * Binning.js
46256 *
46257 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
46258 *
46259 * This library is free software; you can redistribute it and/or
46260 * modify it under the terms of the GNU Lesser General Public
46261 * License as published by the Free Software Foundation; either
46262 * version 3 of the License, or (at your option) any later version.
46263 *
46264 * This library is distributed in the hope that it will be useful,
46265 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46266 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
46267 * Lesser General Public License for more details.
46268 *
46269 * You should have received a copy of the GNU Lesser General Public
46270 * License along with this library; if not, write to the Free Software
46271 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
46272 * MA 02110-1301 USA
46273 */
46274
46275 /**
46276 * @class Binning
46277 * Calculates map aggregation with several binning algorithms
46278 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
46279 * @release 1.0
46280 * @release date: 2012-07-27
46281 * @version date: 2012-07-27
46282 */
46283 Binning = function(map, options) {
46284
46285 this.map = map;
46286 this.options = options;
46287 this.reset();
46288
46289 };
46290
46291 Binning.prototype = {
46292
46293 getSet : function() {
46294 var type = this.options.binning;
46295 if (!type) {
46296 return this.getExactBinning();
46297 } else if (type == 'generic') {
46298 return this.getGenericBinning();
46299 } else if (type == 'square') {
46300 return this.getSquareBinning();
46301 } else if (type == 'hexagonal') {
46302 return this.getHexagonalBinning();
46303 } else if (type == 'triangular') {
46304 return this.getTriangularBinning();
46305 }
46306 },
46307
46308 getExactBinning : function() {
46309 if ( typeof this.binnings['exact'] == 'undefined') {
46310 this.exactBinning();
46311 }
46312 return this.binnings['exact'];
46313 },
46314
46315 getGenericBinning : function() {
46316 if ( typeof this.binnings['generic'] == 'undefined') {
46317 this.genericBinning();
46318 }
46319 return this.binnings['generic'];
46320 },
46321
46322 getSquareBinning : function() {
46323 if ( typeof this.binnings['square'] == 'undefined') {
46324 this.squareBinning();
46325 }
46326 return this.binnings['square'];
46327 },
46328
46329 getHexagonalBinning : function() {
46330 if ( typeof this.binnings['hexagonal'] == 'undefined') {
46331 this.hexagonalBinning();
46332 }
46333 return this.binnings['hexagonal'];
46334 },
46335
46336 getTriangularBinning : function() {
46337 if ( typeof this.binnings['triangular'] == 'undefined') {
46338 this.triangularBinning();
46339 }
46340 return this.binnings['triangular'];
46341 },
46342
46343 reset : function() {
46344 this.zoomLevels = this.map.getNumZoomLevels();
46345 this.binnings = [];
46346 this.minimumRadius = this.options.minimumRadius;
46347 this.maximumRadius = this.minimumRadius;
46348 this.maximumPoints = 0;
46349 this.minArea = 0;
46350 this.maxArea = 0;
46351 },
46352
46353 getMaxRadius : function(size) {
46354 return 4 * Math.log(size) / Math.log(2);
46355 },
46356
46357 setObjects : function(objects) {
46358 this.objects = objects;
46359 for (var i = 0; i < this.objects.length; i++) {
46360 var weight = 0;
46361 for (var j = 0; j < this.objects[i].length; j++) {
46362 if (this.objects[i][j].isGeospatial) {
46363 weight += this.objects[i][j].weight;
46364 }
46365 }
46366 var r = this.getMaxRadius(weight);
46367 if (r > this.maximumRadius) {
46368 this.maximumRadius = r;
46369 this.maximumPoints = weight;
46370 this.maxArea = Math.PI * this.maximumRadius * this.maximumRadius;
46371 this.minArea = Math.PI * this.minimumRadius * this.minimumRadius;
46372 }
46373 }
46374 },
46375
46376 dist : function(x1, y1, x2, y2) {
46377 return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
46378 },
46379
46380 exactBinning : function() {
46381 var circleSets = [];
46382 var hashMaps = [];
46383 var selectionHashs = [];
46384
46385 var circleAggregates = [];
46386 var bins = [];
46387 for (var i = 0; i < this.objects.length; i++) {
46388 bins.push([]);
46389 circleAggregates.push([]);
46390 for (var j = 0; j < this.objects[i].length; j++) {
46391 var o = this.objects[i][j];
46392 if (o.isGeospatial) {
46393 if ( typeof circleAggregates[i]['' + o.getLongitude(this.options.mapIndex)] == 'undefined') {
46394 circleAggregates[i]['' + o.getLongitude(this.options.mapIndex)] = [];
46395 }
46396 if ( typeof circleAggregates[i][''+o.getLongitude(this.options.mapIndex)]['' + o.getLatitude(this.options.mapIndex)] == 'undefined') {
46397 circleAggregates[i][''+o.getLongitude(this.options.mapIndex)]['' + o.getLatitude(this.options.mapIndex)] = [];
46398 bins[i].push(circleAggregates[i][''+o.getLongitude(this.options.mapIndex)]['' + o.getLatitude(this.options.mapIndex)]);
46399 }
46400 circleAggregates[i][''+o.getLongitude(this.options.mapIndex)]['' + o.getLatitude(this.options.mapIndex)].push(o);
46401 }
46402 }
46403 }
46404
46405 var circles = [];
46406 var hashMap = [];
46407 var selectionMap = [];
46408 for (var i = 0; i < bins.length; i++) {
46409 circles.push([]);
46410 hashMap.push([]);
46411 selectionMap.push([]);
46412 for (var j = 0; j < bins[i].length; j++) {
46413 var bin = bins[i][j];
46414 var p = new OpenLayers.Geometry.Point(bin[0].getLongitude(this.options.mapIndex), bin[0].getLatitude(this.options.mapIndex), null);
46415 p.transform(this.map.displayProjection, this.map.projection);
46416 var weight = 0;
46417 for (var z = 0; z < bin.length; z++) {
46418 weight += bin[z].weight;
46419 }
46420 var radius = this.options.minimumRadius;
46421 if (this.options.noBinningRadii == 'dynamic') {
46422 radius = this.getRadius(weight);
46423 }
46424 var circle = new CircleObject(p.x, p.y, 0, 0, bin, radius, i, weight);
46425 circles[i].push(circle);
46426 for (var z = 0; z < bin.length; z++) {
46427 hashMap[i][bin[z].index] = circle;
46428 selectionMap[i][bin[z].index] = false;
46429 }
46430 }
46431 }
46432 for (var k = 0; k < this.zoomLevels; k++) {
46433 circleSets.push(circles);
46434 hashMaps.push(hashMap);
46435 selectionHashs.push(selectionMap);
46436 }
46437 this.binnings['exact'] = {
46438 circleSets : circleSets,
46439 hashMaps : hashMaps,
46440 selectionHashs : selectionHashs
46441 };
46442 },
46443
46444 genericClustering : function(objects, id) {
46445 var binSets = [];
46446 var circleSets = [];
46447 var hashMaps = [];
46448 var selectionHashs = [];
46449 var clustering = new Clustering(-20037508.34, -20037508.34, 20037508.34, 20037508.34);
46450 for (var i = 0; i < objects.length; i++) {
46451 for (var j = 0; j < objects[i].length; j++) {
46452 var o = objects[i][j];
46453 if (o.isGeospatial) {
46454 var p = new OpenLayers.Geometry.Point(o.getLongitude(this.options.mapIndex), o.getLatitude(this.options.mapIndex), null);
46455 p.transform(this.map.displayProjection, this.map.projection);
46456 var point = new Vertex(Math.floor(p.x), Math.floor(p.y), objects.length, this);
46457 point.addElement(o, o.weight, i);
46458 clustering.add(point);
46459 }
46460 }
46461 }
46462
46463 for (var i = 0; i < this.zoomLevels; i++) {
46464 var bins = [];
46465 var circles = [];
46466 var hashMap = [];
46467 var selectionMap = [];
46468 for (var j = 0; j < objects.length; j++) {
46469 circles.push([]);
46470 hashMap.push([]);
46471 selectionMap.push([]);
46472 }
46473 var resolution = this.map.getResolutionForZoom(this.zoomLevels - i - 1);
46474 clustering.mergeForResolution(resolution, this.options.circleGap, this.options.circleOverlap);
46475 for (var j = 0; j < clustering.vertices.length; j++) {
46476 var point = clustering.vertices[j];
46477 if (!point.legal) {
46478 continue;
46479 }
46480 var balls = [];
46481 for (var k = 0; k < point.elements.length; k++) {
46482 if (point.elements[k].length > 0) {
46483 balls.push({
46484 search : k,
46485 elements : point.elements[k],
46486 radius : point.radii[k],
46487 weight : point.weights[k]
46488 });
46489 }
46490 }
46491 var orderBalls = function(b1, b2) {
46492 if (b1.radius > b2.radius) {
46493 return -1;
46494 }
46495 if (b2.radius > b1.radius) {
46496 return 1;
46497 }
46498 return 0;
46499 }
46500 var fatherBin = {
46501 circles : [],
46502 length : 0,
46503 radius : point.radius / resolution,
46504 x : point.x,
46505 y : point.y
46506 };
46507 for (var k = 0; k < objects.length; k++) {
46508 fatherBin.circles.push(false);
46509 }
46510 var createCircle = function(sx, sy, ball) {
46511 var index = id || ball.search;
46512 var circle = new CircleObject(point.x, point.y, sx, sy, ball.elements, ball.radius, index, ball.weight, fatherBin);
46513 circles[ball.search].push(circle);
46514 fatherBin.circles[index] = circle;
46515 fatherBin.length++;
46516 for (var k = 0; k < ball.elements.length; k++) {
46517 hashMap[ball.search][ball.elements[k].index] = circle;
46518 selectionMap[ball.search][ball.elements[k].index] = false;
46519 }
46520 }
46521 if (balls.length == 1) {
46522 createCircle(0, 0, balls[0]);
46523 } else if (balls.length == 2) {
46524 var r1 = balls[0].radius;
46525 var r2 = balls[1].radius;
46526 createCircle(-1 * r2, 0, balls[0]);
46527 createCircle(r1, 0, balls[1]);
46528 } else if (balls.length == 3) {
46529 balls.sort(orderBalls);
46530 var r1 = balls[0].radius;
46531 var r2 = balls[1].radius;
46532 var r3 = balls[2].radius;
46533 var d = ((2 / 3 * Math.sqrt(3) - 1) / 2) * r2;
46534 var delta1 = point.radius / resolution - r1 - d;
46535 var delta2 = r1 - delta1;
46536 createCircle(-delta1, 0, balls[0]);
46537 createCircle(delta2 + r2 - 3 * d, r2, balls[1]);
46538 createCircle(delta2 + r2 - 3 * d, -1 * r3, balls[2]);
46539 // createCircle(delta2 + r3 - (3 * d * r3 / r2), -1 * r3, balls[2]);
46540 } else if (balls.length == 4) {
46541 balls.sort(orderBalls);
46542 var r1 = balls[0].radius;
46543 var r2 = balls[1].radius;
46544 var r3 = balls[2].radius;
46545 var r4 = balls[3].radius;
46546 var d = (Math.sqrt(2) - 1) * r2;
46547 createCircle(-1 * d - r2, 0, balls[0]);
46548 createCircle(r1 - r2, -1 * d - r4, balls[3]);
46549 createCircle(r1 - r2, d + r3, balls[2]);
46550 createCircle(d + r1, 0, balls[1]);
46551 }
46552 if (fatherBin.length > 1) {
46553 bins.push(fatherBin);
46554 }
46555 }
46556 circleSets.push(circles);
46557 binSets.push(bins);
46558 hashMaps.push(hashMap);
46559 selectionHashs.push(selectionMap);
46560 }
46561 circleSets.reverse();
46562 binSets.reverse();
46563 hashMaps.reverse();
46564 selectionHashs.reverse();
46565 return {
46566 circleSets : circleSets,
46567 binSets : binSets,
46568 hashMaps : hashMaps,
46569 selectionHashs : selectionHashs
46570 };
46571 },
46572
46573 genericBinning : function() {
46574 if (this.options.circlePackings || this.objects.length == 1) {
46575 this.binnings['generic'] = this.genericClustering(this.objects);
46576 } else {
46577 var circleSets = [];
46578 var hashMaps = [];
46579 var selectionHashs = [];
46580 for (var i = 0; i < this.objects.length; i++) {
46581 var sets = this.genericClustering([this.objects[i]], i);
46582 if (i == 0) {
46583 circleSets = sets.circleSets;
46584 hashMaps = sets.hashMaps;
46585 selectionHashs = sets.selectionHashs;
46586 } else {
46587 for (var j = 0; j < circleSets.length; j++) {
46588 circleSets[j] = circleSets[j].concat(sets.circleSets[j]);
46589 hashMaps[j] = hashMaps[j].concat(sets.hashMaps[j]);
46590 selectionHashs[j] = selectionHashs[j].concat(sets.selectionHashs[j]);
46591 }
46592 }
46593 }
46594 this.binnings['generic'] = {
46595 circleSets : circleSets,
46596 hashMaps : hashMaps,
46597 selectionHashs : selectionHashs
46598 };
46599 }
46600 },
46601
46602 getRadius : function(n) {
46603 if (n == 0) {
46604 return 0;
46605 }
46606 if (n == 1) {
46607 return this.minimumRadius;
46608 }
46609 return Math.sqrt((this.minArea + (this.maxArea - this.minArea) / (this.maximumPoints - 1) * (n - 1) ) / Math.PI);
46610 },
46611
46612 getBinRadius : function(n, r_max, N) {
46613 if (n == 0) {
46614 return 0;
46615 }
46616 /*
46617 function log2(x) {
46618 return (Math.log(x)) / (Math.log(2));
46619 }
46620 var r0 = this.options.minimumRadius;
46621 var r;
46622 if ( typeof r_max == 'undefined') {
46623 return r0 + n / Math.sqrt(this.options.maximumPoints);
46624 }
46625 return r0 + (r_max - r0 ) * log2(n) / log2(N);
46626 */
46627 var minArea = Math.PI * this.options.minimumRadius * this.options.minimumRadius;
46628 var maxArea = Math.PI * r_max * r_max;
46629 return Math.sqrt((minArea + (maxArea - minArea) / (N - 1) * (n - 1) ) / Math.PI);
46630 },
46631
46632 shift : function(type, bin, radius, elements) {
46633
46634 var x1 = bin.x, x2 = 0;
46635 var y1 = bin.y, y2 = 0;
46636 for (var i = 0; i < elements.length; i++) {
46637 x2 += elements[i].x / elements.length;
46638 y2 += elements[i].y / elements.length;
46639 }
46640
46641 var sx = 0, sy = 0;
46642
46643 if (type == 'square') {
46644 var dx = Math.abs(x2 - x1);
46645 var dy = Math.abs(y2 - y1);
46646 var m = dy / dx;
46647 var n = y1 - m * x1;
46648 if (dx > dy) {
46649 sx = bin.x - (x1 + bin.r - radius );
46650 sy = bin.y - (m * bin.x + n );
46651 } else {
46652 sy = bin.y - (y1 + bin.r - radius );
46653 sx = bin.x - (bin.y - n) / m;
46654 }
46655 }
46656
46657 return {
46658 x : sx,
46659 y : sy
46660 };
46661
46662 },
46663
46664 binSize : function(elements) {
46665 var size = 0;
46666 for (var i in elements ) {
46667 size += elements[i].weight;
46668 }
46669 return size;
46670 },
46671
46672 setCircleSet : function(id, binData) {
46673 var circleSets = [];
46674 var hashMaps = [];
46675 var selectionHashs = [];
46676 for (var i = 0; i < binData.length; i++) {
46677 var circles = [];
46678 var hashMap = [];
46679 var selectionMap = [];
46680 for (var j = 0; j < this.objects.length; j++) {
46681 circles.push([]);
46682 hashMap.push([]);
46683 selectionMap.push([]);
46684 }
46685 var points = [];
46686 var max = 0;
46687 var radius = 0;
46688 var resolution = this.map.getResolutionForZoom(i);
46689 for (var j = 0; j < binData[i].length; j++) {
46690 for (var k = 0; k < binData[i][j].bin.length; k++) {
46691 var bs = this.binSize(binData[i][j].bin[k]);
46692 if (bs > max) {
46693 max = bs;
46694 radius = binData[i][j].r / resolution;
46695 }
46696 }
46697 }
46698 for (var j = 0; j < binData[i].length; j++) {
46699 var bin = binData[i][j];
46700 for (var k = 0; k < bin.bin.length; k++) {
46701 if (bin.bin[k].length == 0) {
46702 continue;
46703 }
46704 var weight = this.binSize(bin.bin[k]);
46705 var r = this.getBinRadius(weight, radius, max);
46706 var shift = this.shift(id, bin, r * resolution, bin.bin[k], i);
46707 var circle = new CircleObject(bin.x - shift.x, bin.y - shift.y, 0, 0, bin.bin[k], r, k, weight);
46708 circles[k].push(circle);
46709 for (var z = 0; z < bin.bin[k].length; z++) {
46710 hashMap[k][bin.bin[k][z].index] = circle;
46711 selectionMap[k][bin.bin[k][z].index] = false;
46712 }
46713 }
46714 }
46715 circleSets.push(circles);
46716 hashMaps.push(hashMap);
46717 selectionHashs.push(selectionMap);
46718 }
46719 this.binnings[id] = {
46720 circleSets : circleSets,
46721 hashMaps : hashMaps,
46722 selectionHashs : selectionHashs
46723 };
46724 },
46725
46726 squareBinning : function() {
46727
46728 var l = 20037508.34;
46729 var area0 = l * l * 4;
46730 var binCount = this.options.binCount;
46731
46732 var bins = [];
46733 var binData = [];
46734 for (var k = 0; k < this.zoomLevels; k++) {
46735 bins.push([]);
46736 binData.push([]);
46737 }
46738
46739 for (var i = 0; i < this.objects.length; i++) {
46740 for (var j = 0; j < this.objects[i].length; j++) {
46741 var o = this.objects[i][j];
46742 if (!o.isGeospatial) {
46743 continue;
46744 }
46745 var p = new OpenLayers.Geometry.Point(o.getLongitude(this.options.mapIndex), o.getLatitude(this.options.mapIndex), null);
46746 p.transform(this.map.displayProjection, this.map.projection);
46747 o.x = p.x;
46748 o.y = p.y;
46749 for (var k = 0; k < this.zoomLevels; k++) {
46750 var bc = binCount * Math.pow(2, k);
46751 var a = 2 * l / bc;
46752 var binX = Math.floor((p.x + l) / (2 * l) * bc);
46753 var binY = Math.floor((p.y + l) / (2 * l) * bc);
46754 if ( typeof bins[k]['' + binX] == 'undefined') {
46755 bins[k]['' + binX] = [];
46756 }
46757 if ( typeof bins[k][''+binX]['' + binY] == 'undefined') {
46758 bins[k][''+binX]['' + binY] = [];
46759 for (var z = 0; z < this.objects.length; z++) {
46760 bins[k][''+binX]['' + binY].push([]);
46761 }
46762 var x = binX * a + a / 2 - l;
46763 var y = binY * a + a / 2 - l;
46764 binData[k].push({
46765 bin : bins[k][''+binX]['' + binY],
46766 x : x,
46767 y : y,
46768 a : a,
46769 r : a / 2
46770 });
46771 }
46772 bins[k][''+binX][''+binY][i].push(o);
46773 }
46774 }
46775 }
46776
46777 this.setCircleSet('square', binData);
46778
46779 },
46780
46781 triangularBinning : function() {
46782
46783 var l = 20037508.34;
46784 var a0 = this.options.binCount;
46785 var a1 = Math.sqrt(4 * a0 * a0 / Math.sqrt(3));
46786 var binCount = a0 / a1 * a0;
46787
46788 var bins = [];
46789 var binData = [];
46790 for (var k = 0; k < this.zoomLevels; k++) {
46791 bins.push([]);
46792 binData.push([]);
46793 }
46794
46795 for (var i = 0; i < this.objects.length; i++) {
46796 for (var j = 0; j < this.objects[i].length; j++) {
46797 var o = this.objects[i][j];
46798 if (!o.isGeospatial) {
46799 continue;
46800 }
46801 var p = new OpenLayers.Geometry.Point(o.getLongitude(this.options.mapIndex), o.getLatitude(this.options.mapIndex), null);
46802 p.transform(this.map.displayProjection, this.map.projection);
46803 o.x = p.x;
46804 o.y = p.y;
46805 for (var k = 0; k < this.zoomLevels; k++) {
46806 var x_bc = binCount * Math.pow(2, k);
46807 var y_bc = x_bc * x_bc / Math.sqrt(x_bc * x_bc - x_bc * x_bc / 4);
46808 var a = 2 * l / x_bc;
46809 var h = 2 * l / y_bc;
46810 var binY = Math.floor((p.y + l) / (2 * l) * y_bc);
46811 if ( typeof bins[k]['' + binY] == 'undefined') {
46812 bins[k]['' + binY] = [];
46813 }
46814 var triangleIndex;
46815 var partitionsX = x_bc * 2;
46816 var partition = Math.floor((p.x + l) / (2 * l) * partitionsX);
46817 var xMax = a / 2;
46818 var yMax = h;
46819 var x = p.x + l - partition * a / 2;
46820 var y = p.y + l - binY * h;
46821 if (binY % 2 == 0 && partition % 2 == 1 || binY % 2 == 1 && partition % 2 == 0) {
46822 if (y + yMax / xMax * x < yMax) {
46823 triangleIndex = partition;
46824 } else {
46825 triangleIndex = partition + 1;
46826 }
46827 } else {
46828 if (y > yMax / xMax * x) {
46829 triangleIndex = partition;
46830 } else {
46831 triangleIndex = partition + 1;
46832 }
46833 }
46834 if ( typeof bins[k][''+binY]['' + triangleIndex] == 'undefined') {
46835 bins[k][''+binY]['' + triangleIndex] = [];
46836 for (var z = 0; z < this.objects.length; z++) {
46837 bins[k][''+binY]['' + triangleIndex].push([]);
46838 }
46839 var r = Math.sqrt(3) / 6 * a;
46840 var x = (triangleIndex - 1) * a / 2 + a / 2 - l;
46841 var y;
46842 if (binY % 2 == 0 && triangleIndex % 2 == 0 || binY % 2 == 1 && triangleIndex % 2 == 1) {
46843 y = binY * h + h - r - l;
46844 } else {
46845 y = binY * h + r - l;
46846 }
46847 binData[k].push({
46848 bin : bins[k][''+binY]['' + triangleIndex],
46849 x : x,
46850 y : y,
46851 a : a,
46852 r : r
46853 });
46854 }
46855 bins[k][''+binY][''+triangleIndex][i].push(o);
46856 }
46857 }
46858 }
46859
46860 this.setCircleSet('triangular', binData);
46861
46862 },
46863
46864 hexagonalBinning : function() {
46865
46866 var l = 20037508.34;
46867 var a0 = this.options.binCount;
46868 var a2 = Math.sqrt(4 * a0 * a0 / Math.sqrt(3)) / Math.sqrt(6);
46869 var binCount = a0 / a2 * a0;
46870
46871 var bins = [];
46872 var binData = [];
46873 for (var k = 0; k < this.zoomLevels; k++) {
46874 bins.push([]);
46875 binData.push([]);
46876 }
46877
46878 for (var i = 0; i < this.objects.length; i++) {
46879 for (var j = 0; j < this.objects[i].length; j++) {
46880 var o = this.objects[i][j];
46881 if (!o.isGeospatial) {
46882 continue;
46883 }
46884 var p = new OpenLayers.Geometry.Point(o.getLongitude(this.options.mapIndex), o.getLatitude(this.options.mapIndex), null);
46885 p.transform(this.map.displayProjection, this.map.projection);
46886 o.x = p.x;
46887 o.y = p.y;
46888 for (var k = 0; k < this.zoomLevels; k++) {
46889 var x_bc = binCount * Math.pow(2, k);
46890 var y_bc = x_bc * x_bc / Math.sqrt(x_bc * x_bc - x_bc * x_bc / 4);
46891 var a = 2 * l / x_bc;
46892 var h = 2 * l / y_bc;
46893 var binY = Math.floor((p.y + l) / (2 * l) * y_bc);
46894 if ( typeof bins[k]['' + binY] == 'undefined') {
46895 bins[k]['' + binY] = [];
46896 }
46897 var triangleIndex;
46898 var partitionsX = x_bc * 2;
46899 var partition = Math.floor((p.x + l) / (2 * l) * partitionsX);
46900 var xMax = a / 2;
46901 var yMax = h;
46902 var x = p.x + l - partition * a / 2;
46903 var y = p.y + l - binY * h;
46904 if (binY % 2 == 0 && partition % 2 == 1 || binY % 2 == 1 && partition % 2 == 0) {
46905 if (y + yMax / xMax * x < yMax) {
46906 triangleIndex = partition;
46907 } else {
46908 triangleIndex = partition + 1;
46909 }
46910 } else {
46911 if (y > yMax / xMax * x) {
46912 triangleIndex = partition;
46913 } else {
46914 triangleIndex = partition + 1;
46915 }
46916 }
46917 if ( typeof bins[k][''+binY]['' + triangleIndex] == 'undefined') {
46918 bins[k][''+binY]['' + triangleIndex] = [];
46919 for (var z = 0; z < this.objects.length; z++) {
46920 bins[k][''+binY]['' + triangleIndex].push([]);
46921 }
46922 var r = Math.sqrt(3) / 6 * a;
46923 var x = (triangleIndex - 1) * a / 2 + a / 2 - l;
46924 var y;
46925 if (binY % 2 == 0 && triangleIndex % 2 == 0 || binY % 2 == 1 && triangleIndex % 2 == 1) {
46926 y = binY * h + h - r - l;
46927 } else {
46928 y = binY * h + r - l;
46929 }
46930 binData[k].push({
46931 bin : bins[k][''+binY]['' + triangleIndex],
46932 x : x,
46933 y : y,
46934 a : a,
46935 r : r,
46936 h : h,
46937 binX : triangleIndex,
46938 binY : binY
46939 });
46940 }
46941 bins[k][''+binY][''+triangleIndex][i].push(o);
46942 }
46943 }
46944 }
46945
46946 var hexaBins = [];
46947 var hexaBinData = [];
46948 for (var k = 0; k < this.zoomLevels; k++) {
46949 hexaBins.push([]);
46950 hexaBinData.push([]);
46951 }
46952
46953 for (var i = 0; i < binData.length; i++) {
46954 for (var j = 0; j < binData[i].length; j++) {
46955 var bin = binData[i][j];
46956 var binY = Math.floor(bin.binY / 2);
46957 var binX = Math.floor(bin.binX / 3);
46958 var x, y;
46959 var a = bin.a;
46960 var h = bin.h;
46961 if (bin.binX % 6 < 3) {
46962 if ( typeof hexaBins[i]['' + binY] == 'undefined') {
46963 hexaBins[i]['' + binY] = [];
46964 }
46965 y = binY * 2 * bin.h + bin.h - l;
46966 x = binX * 1.5 * bin.a + a / 2 - l;
46967 } else {
46968 if (bin.binY % 2 == 1) {
46969 binY++;
46970 }
46971 if ( typeof hexaBins[i]['' + binY] == 'undefined') {
46972 hexaBins[i]['' + binY] = [];
46973 }
46974 y = binY * 2 * bin.h - l;
46975 x = binX * 1.5 * bin.a + a / 2 - l;
46976 }
46977 if ( typeof hexaBins[i][''+binY]['' + binX] == 'undefined') {
46978 hexaBins[i][''+binY]['' + binX] = [];
46979 for (var z = 0; z < this.objects.length; z++) {
46980 hexaBins[i][''+binY]['' + binX].push([]);
46981 }
46982 hexaBinData[i].push({
46983 bin : hexaBins[i][''+binY]['' + binX],
46984 x : x,
46985 y : y,
46986 a : bin.a,
46987 r : bin.h
46988 });
46989 }
46990 for (var k = 0; k < bin.bin.length; k++) {
46991 for (var m = 0; m < bin.bin[k].length; m++) {
46992 hexaBins[i][''+binY][''+binX][k].push(bin.bin[k][m]);
46993 }
46994 }
46995 }
46996 }
46997
46998 this.setCircleSet('hexagonal', hexaBinData);
46999
47000 }
47001 }
47002
47003 /*
47004 * MapDataSource.js
47005 *
47006 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
47007 *
47008 * This library is free software; you can redistribute it and/or
47009 * modify it under the terms of the GNU Lesser General Public
47010 * License as published by the Free Software Foundation; either
47011 * version 3 of the License, or (at your option) any later version.
47012 *
47013 * This library is distributed in the hope that it will be useful,
47014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47016 * Lesser General Public License for more details.
47017 *
47018 * You should have received a copy of the GNU Lesser General Public
47019 * License along with this library; if not, write to the Free Software
47020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
47021 * MA 02110-1301 USA
47022 */
47023
47024 /**
47025 * @class MapDataSource
47026 * implementation for aggregation of map items
47027 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
47028 * @release 1.0
47029 * @release date: 2012-07-27
47030 * @version date: 2012-07-27
47031 *
47032 * @param {MapWidget} parent Widget
47033 * @param {JSON} options map configuration
47034 */
47035 function MapDataSource(parent, options) {
47036
47037 this.parent = parent;
47038 this.olMap = parent.openlayersMap;
47039 this.circleSets = [];
47040 this.binning = new Binning(this.olMap, options);
47041
47042 };
47043
47044 MapDataSource.prototype = {
47045
47046 /**
47047 * initializes the MapDataSource
47048 * @param {MapObject[][]} mapObjects an array of map objects of different sets
47049 */
47050 initialize : function(mapObjects) {
47051
47052 if (mapObjects != this.mapObjects) {
47053 this.binning.reset();
47054 this.binning.setObjects(mapObjects);
47055 }
47056 this.mapObjects = mapObjects;
47057
47058 var set = this.binning.getSet();
47059 this.circleSets = set.circleSets;
47060 this.binSets = set.binSets;
47061 this.hashMapping = set.hashMaps;
47062
47063 },
47064
47065 getObjectsByZoom : function() {
47066 var zoom = Math.floor(this.parent.getZoom());
47067 if (this.circleSets.length < zoom) {
47068 return null;
47069 }
47070 return this.circleSets[zoom];
47071 },
47072
47073 getAllObjects : function() {
47074 if (this.circleSets.length == 0) {
47075 return null;
47076 }
47077 return this.circleSets;
47078 },
47079
47080 getAllBins : function() {
47081 if (this.binSets.length == 0) {
47082 return null;
47083 }
47084 return this.binSets;
47085 },
47086
47087 clearOverlay : function() {
47088 var zoom = Math.floor(this.parent.getZoom());
47089 var circles = this.circleSets[zoom];
47090 for (var i in circles ) {
47091 for (var j in circles[i] ) {
47092 circles[i][j].reset();
47093 }
47094 }
47095 },
47096
47097 setOverlay : function(mapObjects) {
47098 var zoom = Math.floor(this.parent.getZoom());
47099 for (var j in mapObjects ) {
47100 for (var k in mapObjects[j] ) {
47101 var o = mapObjects[j][k];
47102 if (o.isGeospatial) {
47103 this.hashMapping[zoom][j][o.index].overlayElements.push(o);
47104 this.hashMapping[zoom][j][o.index].overlay += o.weight;
47105 }
47106 }
47107 }
47108 },
47109
47110 size : function() {
47111 if (this.circleSets.length == 0) {
47112 return 0;
47113 }
47114 return this.circleSets[0].length;
47115 },
47116
47117 getCircle : function(index, id) {
47118 var zoom = Math.floor(this.parent.getZoom());
47119 return this.hashMapping[zoom][index][id];
47120 }
47121 };
47122 /*
47123 * Clustering.js
47124 *
47125 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
47126 *
47127 * This library is free software; you can redistribute it and/or
47128 * modify it under the terms of the GNU Lesser General Public
47129 * License as published by the Free Software Foundation; either
47130 * version 3 of the License, or (at your option) any later version.
47131 *
47132 * This library is distributed in the hope that it will be useful,
47133 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47134 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47135 * Lesser General Public License for more details.
47136 *
47137 * You should have received a copy of the GNU Lesser General Public
47138 * License along with this library; if not, write to the Free Software
47139 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
47140 * MA 02110-1301 USA
47141 */
47142
47143 /**
47144 * @class Vertex, Edge, Triangle, Clustering, BinaryHeap
47145 * Dynamic Delaunay clustering algorithm (see GeoTemCo paper)
47146 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
47147 * @release 1.0
47148 * @release date: 2012-07-27
47149 * @version date: 2012-07-27
47150 */
47151
47152 function Vertex(x, y, categories, binning) {
47153 this.x = x;
47154 this.y = y;
47155 this.radius
47156 this.size = 0;
47157 this.elements = [];
47158 this.radii = [];
47159 this.weights = [];
47160 this.legal = true;
47161 this.binning = binning;
47162 if (categories != undefined) {
47163 for (var i = 0; i < categories; i++) {
47164 this.elements.push([]);
47165 this.weights.push(0);
47166 }
47167 }
47168 }
47169
47170 Vertex.prototype.merge = function(v0, v1) {
47171 for (var i = 0; i < v0.elements.length; i++) {
47172 this.elements[i] = v0.elements[i].concat(v1.elements[i]);
47173 this.weights[i] = v0.weights[i] + v1.weights[i];
47174 this.size += this.weights[i];
47175 }
47176 }
47177
47178 Vertex.prototype.CalculateRadius = function(resolution) {
47179 this.radii = [];
47180 for (i in this.elements ) {
47181 this.radii.push(this.binning.getRadius(this.weights[i]));
47182 }
47183 if (this.radii.length == 1) {
47184 this.radius = this.radii[0] * resolution;
47185 } else {
47186 var count = 0;
47187 var max1 = 0;
47188 var max2 = 0;
47189 for (i in this.radii ) {
47190 if (this.radii[i] != 0) {
47191 count++;
47192 }
47193 if (this.radii[i] > max1) {
47194 if (max1 > max2) {
47195 max2 = max1;
47196 }
47197 max1 = this.radii[i];
47198 } else if (this.radii[i] > max2) {
47199 max2 = this.radii[i];
47200 }
47201 }
47202 if (count == 1) {
47203 this.radius = max1 * resolution;
47204 } else if (count == 2) {
47205 this.radius = (max1 + max2) * resolution;
47206 } else if (count == 3) {
47207 var d = (2 / 3 * Math.sqrt(3) - 1) * max1;
47208 this.radius = (d + max1 + max2) * resolution;
47209 } else if (count == 4) {
47210 var d = (Math.sqrt(2) - 1) * max2;
47211 this.radius = (d + max1 + max2) * resolution;
47212 }
47213 }
47214 }
47215
47216 Vertex.prototype.addElement = function(e, weight, index) {
47217 this.elements[index].push(e);
47218 this.size += weight;
47219 this.weights[index] += weight;
47220 }
47221 function Edge(v0, v1) {
47222 this.v0 = v0;
47223 this.v1 = v1;
47224 this.leftFace
47225 this.rightFace
47226 this.legal = true;
47227 this.setLength();
47228 }
47229
47230 Edge.prototype.setLength = function() {
47231 var dx = this.v0.x - this.v1.x;
47232 var dy = this.v0.y - this.v1.y;
47233 this.length = Math.sqrt(dx * dx + dy * dy);
47234 }
47235
47236 Edge.prototype.contains = function(v) {
47237 if (this.v0 == v || this.v1 == v) {
47238 return true;
47239 }
47240 return false;
47241 }
47242
47243 Edge.prototype.replaceFace = function(f_old, f_new) {
47244 if (this.leftFace == f_old) {
47245 this.leftFace = f_new;
47246 } else if (this.rightFace == f_old) {
47247 this.rightFace = f_new;
47248 }
47249 }
47250
47251 Edge.prototype.setFace = function(f) {
47252 if (f.leftOf(this)) {
47253 this.leftFace = f;
47254 } else {
47255 this.rightFace = f;
47256 }
47257 }
47258
47259 Edge.prototype.setFaces = function(f1, f2) {
47260 if (f1.leftOf(this)) {
47261 this.leftFace = f1;
47262 this.rightFace = f2;
47263 } else {
47264 this.leftFace = f2;
47265 this.rightFace = f1;
47266 }
47267 }
47268
47269 Edge.prototype.removeFace = function(f) {
47270 if (this.leftFace == f) {
47271 this.leftFace = null;
47272 } else {
47273 this.rightFace = null;
47274 }
47275 }
47276
47277 Edge.prototype.equals = function(e) {
47278 if (this.v0 == e.v0 && this.v1 == e.v1 || this.v0 == e.v1 && this.v1 == e.v0) {
47279 return true;
47280 }
47281 return false;
47282 }
47283 function Triangle(edges) {
47284 this.edges = edges;
47285 this.setVertices();
47286 this.descendants = [];
47287 }
47288
47289 Triangle.prototype.getTriple = function(e) {
47290 var i = arrayIndex(this.edges, e);
47291 return {
47292 e_s : this.edges[(i + 1) % 3],
47293 e_p : this.edges[(i + 2) % 3],
47294 u : this.vertices[(i + 2) % 3]
47295 };
47296 }
47297
47298 Triangle.prototype.leftOf = function(e) {
47299 var i = arrayIndex(this.edges, e);
47300 if (this.vertices[i].y != this.vertices[(i + 1) % 3].y) {
47301 return this.vertices[i].y > this.vertices[(i + 1) % 3].y;
47302 }
47303 return this.vertices[i].y > this.vertices[(i + 2) % 3].y;
47304 }
47305
47306 Triangle.prototype.getNext = function(v) {
47307 var i = arrayIndex(this.vertices, v);
47308 return this.vertices[(i + 1) % 3];
47309 }
47310
47311 Triangle.prototype.oppositeEdge = function(v) {
47312 var i = arrayIndex(this.vertices, v);
47313 return this.edges[(i + 1) % 3];
47314 }
47315
47316 Triangle.prototype.contains = function(v) {
47317 return arrayIndex(this.vertices, v) != -1;
47318 }
47319
47320 Triangle.prototype.replace = function(e_old, e_new) {
47321 this.edges[arrayIndex(this.edges, e_old)] = e_new;
47322 }
47323
47324 Triangle.prototype.setVertices = function() {
47325 if (this.edges[1].v0 == this.edges[0].v0 || this.edges[1].v1 == this.edges[0].v0) {
47326 this.vertices = [this.edges[0].v1, this.edges[0].v0];
47327 } else {
47328 this.vertices = [this.edges[0].v0, this.edges[0].v1];
47329 }
47330 if (this.edges[2].v0 == this.vertices[0]) {
47331 this.vertices.push(this.edges[2].v1);
47332 } else {
47333 this.vertices.push(this.edges[2].v0);
47334 }
47335 }
47336
47337 Triangle.prototype.replaceBy = function(triangles) {
47338 this.descendants = triangles;
47339 this.edges[0].replaceFace(this, triangles[0]);
47340 this.edges[1].replaceFace(this, triangles[1]);
47341 this.edges[2].replaceFace(this, triangles[2]);
47342 }
47343
47344 Triangle.prototype.CalcCircumcircle = function() {
47345 var v0 = this.vertices[0];
47346 var v1 = this.vertices[1];
47347 var v2 = this.vertices[2];
47348 var A = v1.x - v0.x;
47349 var B = v1.y - v0.y;
47350 var C = v2.x - v0.x;
47351 var D = v2.y - v0.y;
47352 var E = A * (v0.x + v1.x) + B * (v0.y + v1.y);
47353 var F = C * (v0.x + v2.x) + D * (v0.y + v2.y);
47354 var G = 2.0 * (A * (v2.y - v1.y) - B * (v2.x - v1.x));
47355 var cx = (D * E - B * F) / G;
47356 var cy = (A * F - C * E) / G;
47357 this.center = new Vertex(cx, cy);
47358 var dx = this.center.x - v0.x;
47359 var dy = this.center.y - v0.y;
47360 this.radius_squared = dx * dx + dy * dy;
47361 };
47362
47363 Triangle.prototype.inCircumcircle = function(v) {
47364 if (this.radius_squared == undefined) {
47365 this.CalcCircumcircle();
47366 }
47367 var dx = this.center.x - v.x;
47368 var dy = this.center.y - v.y;
47369 var dist_squared = dx * dx + dy * dy;
47370 return (dist_squared <= this.radius_squared );
47371 };
47372
47373 Triangle.prototype.interior = function(v) {
47374 var v0 = this.vertices[0];
47375 var v1 = this.vertices[1];
47376 var v2 = this.vertices[2];
47377 var dotAB = (v.x - v0.x ) * (v0.y - v1.y ) + (v.y - v0.y ) * (v1.x - v0.x );
47378 var dotBC = (v.x - v1.x ) * (v1.y - v2.y ) + (v.y - v1.y ) * (v2.x - v1.x );
47379 var dotCA = (v.x - v2.x ) * (v2.y - v0.y ) + (v.y - v2.y ) * (v0.x - v2.x );
47380 if (dotAB > 0 || dotBC > 0 || dotCA > 0) {
47381 return null;
47382 } else if (dotAB < 0 && dotBC < 0 && dotCA < 0) {
47383 return this;
47384 } else if (dotAB == 0) {
47385 if (dotBC == 0) {
47386 return this.vertices[1];
47387 } else if (dotCA == 0) {
47388 return this.vertices[0];
47389 }
47390 return this.edges[0];
47391 } else if (dotBC == 0) {
47392 if (dotCA == 0) {
47393 return this.vertices[2];
47394 }
47395 return this.edges[1];
47396 } else if (dotCA == 0) {
47397 return this.edges[2];
47398 }
47399 };
47400
47401 function Clustering(xMin, yMin, xMax, yMax) {
47402 this.triangles = [];
47403 this.newTriangles = [];
47404 this.bbox = {
47405 x1 : xMin,
47406 y1 : yMin,
47407 x2 : xMax,
47408 y2 : yMax
47409 };
47410 this.CreateBoundingTriangle();
47411 this.edges = [];
47412 this.vertices = [];
47413 this.legalizes = 0;
47414 this.collapses = 0;
47415 }
47416
47417 Clustering.prototype.locate = function(v) {
47418 if (this.boundingTriangle.descendants.length == 0) {
47419 return this.boundingTriangle;
47420 }
47421 var triangles = this.boundingTriangle.descendants;
47422 while (true) {
47423 for (var i = 0; i < triangles.length; i++) {
47424 var simplex = triangles[i].interior(v);
47425 if (simplex == null) {
47426 continue;
47427 }
47428 if ( simplex instanceof Vertex || this.isLeaf(triangles[i])) {
47429 return simplex;
47430 }
47431 triangles = triangles[i].descendants;
47432 break;
47433 }
47434 }
47435 }
47436
47437 Clustering.prototype.legalize = function(v, e, t0_old) {
47438 if (!e.v0.legal && !e.v1.legal) {
47439 return;
47440 }
47441 this.legalizes++;
47442 var flip = false;
47443 var t1_old, tr1;
47444 if (e.leftFace == t0_old && e.rightFace.inCircumcircle(v)) {
47445 flip = true;
47446 t1_old = e.rightFace;
47447 } else if (e.rightFace == t0_old && e.leftFace.inCircumcircle(v)) {
47448 flip = true;
47449 t1_old = e.leftFace;
47450 }
47451 if (flip) {
47452 var tr0 = t0_old.getTriple(e);
47453 var tr1 = t1_old.getTriple(e);
47454 var e_flip = new Edge(tr0.u, tr1.u);
47455 var poly = [];
47456 poly.push(e.v0);
47457 poly.push(e_flip.v0);
47458 poly.push(e.v1);
47459 poly.push(e_flip.v1);
47460 if (!this.JordanTest(poly, e_flip)) {
47461 return;
47462 }
47463 e.legal = false;
47464 this.edges.push(e_flip);
47465 var t0_new = new Triangle([e_flip, tr0.e_p, tr1.e_s]);
47466 var t1_new = new Triangle([e_flip, tr1.e_p, tr0.e_s]);
47467 e_flip.setFaces(t0_new, t1_new);
47468 tr0.e_p.replaceFace(t0_old, t0_new);
47469 tr1.e_s.replaceFace(t1_old, t0_new);
47470 tr1.e_p.replaceFace(t1_old, t1_new);
47471 tr0.e_s.replaceFace(t0_old, t1_new);
47472 t0_old.descendants = [t0_new, t1_new];
47473 t1_old.descendants = [t0_new, t1_new];
47474 this.legalize(v, t0_new.edges[2], t0_new);
47475 this.legalize(v, t1_new.edges[1], t1_new);
47476 }
47477 }
47478
47479 Clustering.prototype.add = function(v) {
47480 this.addVertex(v, this.locate(v));
47481 }
47482
47483 Clustering.prototype.addVertex = function(v, simplex) {
47484 if ( simplex instanceof Vertex) {
47485 simplex.merge(simplex, v);
47486 } else if ( simplex instanceof Edge) {
47487 this.vertices.push(v);
47488 simplex.legal = false;
47489 var tr0 = simplex.leftFace.getTriple(simplex);
47490 var tr1 = simplex.rightFace.getTriple(simplex);
47491 var e0 = new Edge(v, tr0.u);
47492 var e1 = new Edge(v, simplex.leftFace.getNext(tr0.u));
47493 var e2 = new Edge(v, tr1.u);
47494 var e3 = new Edge(v, simplex.rightFace.getNext(tr1.u));
47495 var t0 = new Triangle([e0, tr0.e_p, e1]);
47496 var t1 = new Triangle([e1, tr1.e_s, e2]);
47497 var t2 = new Triangle([e2, tr1.e_p, e3]);
47498 var t3 = new Triangle([e3, tr0.e_s, e0]);
47499 simplex.leftFace.descendants = [t0, t3];
47500 simplex.rightFace.descendants = [t1, t2];
47501 this.edges.push(e0);
47502 this.edges.push(e1);
47503 this.edges.push(e2);
47504 this.edges.push(e3);
47505 e0.setFaces(t0, t3);
47506 e1.setFaces(t0, t1);
47507 e2.setFaces(t1, t2);
47508 e3.setFaces(t2, t3);
47509 tr0.e_p.replaceFace(simplex.leftFace, t0);
47510 tr1.e_s.replaceFace(simplex.rightFace, t1);
47511 tr1.e_p.replaceFace(simplex.rightFace, t2);
47512 tr0.e_s.replaceFace(simplex.leftFace, t3);
47513 this.legalize(v, tr0.e_p, t0);
47514 this.legalize(v, tr1.e_s, t1);
47515 this.legalize(v, tr1.e_p, t2);
47516 this.legalize(v, tr0.e_s, t3);
47517 } else {
47518 this.vertices.push(v);
47519 var e_i = new Edge(simplex.vertices[0], v);
47520 var e_j = new Edge(simplex.vertices[1], v);
47521 var e_k = new Edge(simplex.vertices[2], v);
47522 this.edges.push(e_i);
47523 this.edges.push(e_j);
47524 this.edges.push(e_k);
47525 var t0 = new Triangle([e_i, simplex.edges[0], e_j]);
47526 var t1 = new Triangle([e_j, simplex.edges[1], e_k]);
47527 var t2 = new Triangle([e_k, simplex.edges[2], e_i]);
47528 e_i.setFaces(t0, t2);
47529 e_j.setFaces(t0, t1);
47530 e_k.setFaces(t1, t2);
47531 simplex.replaceBy([t0, t1, t2]);
47532 this.legalize(v, simplex.edges[0], t0);
47533 this.legalize(v, simplex.edges[1], t1);
47534 this.legalize(v, simplex.edges[2], t2);
47535 }
47536 }
47537
47538 Clustering.prototype.isLeaf = function(t) {
47539 return t.descendants.length == 0;
47540 }
47541
47542 Clustering.prototype.CreateBoundingTriangle = function() {
47543 var dx = (this.bbox.x2 - this.bbox.x1 ) * 10;
47544 var dy = (this.bbox.y2 - this.bbox.y1 ) * 10;
47545 var v0 = new Vertex(this.bbox.x1 - dx, this.bbox.y1 - dy * 3);
47546 var v1 = new Vertex(this.bbox.x2 + dx * 3, this.bbox.y2 + dy);
47547 var v2 = new Vertex(this.bbox.x1 - dx, this.bbox.y2 + dy);
47548 var e0 = new Edge(v1, v0);
47549 var e1 = new Edge(v0, v2);
47550 var e2 = new Edge(v2, v1);
47551 v0.legal = false;
47552 v1.legal = false;
47553 v2.legal = false;
47554 this.boundingTriangle = new Triangle([e0, e1, e2]);
47555 var inf = new Triangle([e0, e1, e2]);
47556 e0.setFaces(this.boundingTriangle, inf);
47557 e1.setFaces(this.boundingTriangle, inf);
47558 e2.setFaces(this.boundingTriangle, inf);
47559 }
47560
47561 Clustering.prototype.mergeVertices = function(e) {
47562 this.collapses++;
47563 var s0 = e.v0.size;
47564 var s1 = e.v1.size;
47565 var x = (e.v0.x * s0 + e.v1.x * s1 ) / (s0 + s1 );
47566 var y = (e.v0.y * s0 + e.v1.y * s1 ) / (s0 + s1 );
47567 var v = new Vertex(x, y, e.v0.elements.length, e.v0.binning);
47568 v.merge(e.v0, e.v1);
47569
47570 e.v0.legal = false;
47571 e.v1.legal = false;
47572
47573 var hole = [];
47574 var oldFacets = [];
47575 e.legal = false;
47576
47577 var vertices = [];
47578 var traverse = function(eLeft, eRight, triangle) {
47579 eLeft.legal = false;
47580 do {
47581 var triple;
47582 if (eLeft.leftFace == triangle) {
47583 triple = eLeft.rightFace.getTriple(eLeft);
47584 oldFacets.push(eLeft.rightFace);
47585 triple.e_s.removeFace(eLeft.rightFace);
47586 triangle = eLeft.rightFace;
47587 } else {
47588 triple = eLeft.leftFace.getTriple(eLeft);
47589 oldFacets.push(eLeft.leftFace);
47590 triple.e_s.removeFace(eLeft.leftFace);
47591 triangle = eLeft.leftFace;
47592 }
47593 if (arrayIndex(hole, triple.e_s) == -1) {
47594 hole.push(triple.e_s);
47595 }
47596 vertices.push(triple.u);
47597 eLeft = triple.e_p;
47598 eLeft.legal = false;
47599 } while( eLeft != eRight );
47600 }
47601 var tr0 = e.leftFace.getTriple(e);
47602 var tr1 = e.rightFace.getTriple(e);
47603 oldFacets.push(e.leftFace);
47604 oldFacets.push(e.rightFace);
47605 traverse(tr0.e_p, tr1.e_s, e.leftFace);
47606 traverse(tr1.e_p, tr0.e_s, e.rightFace);
47607
47608 var hd = new Clustering(this.bbox.x1 - 10, this.bbox.y1 - 10, this.bbox.x2 + 10, this.bbox.y2 + 10);
47609 var hull = [];
47610 for (var i in hole ) {
47611 if (!(hole[i].leftFace == null && hole[i].rightFace == null)) {
47612 hull.push(hole[i].v0);
47613 hull.push(hole[i].v1);
47614 }
47615 }
47616 var hullVertices = [];
47617 var distinct = [];
47618 for (var i in vertices ) {
47619 if (arrayIndex(distinct, vertices[i]) == -1) {
47620 hd.add(vertices[i]);
47621 distinct.push(vertices[i]);
47622 }
47623 if (arrayIndex(hull, vertices[i]) != -1) {
47624 hullVertices.push(vertices[i]);
47625 }
47626 }
47627
47628 var newFacets = [];
47629 var isBoundary = function(e) {
47630 for (var i = 0; i < hole.length; i++) {
47631 if (hole[i].equals(e)) {
47632 return i;
47633 }
47634 }
47635 return -1;
47636 }
47637 var holeEdges = new Array(hole.length);
47638 var nonHoleEdges = [];
47639
47640 for (var i = 0; i < hd.edges.length; i++) {
47641 var e = hd.edges[i];
47642 var b = isBoundary(e);
47643 if (b != -1) {
47644 if (!e.legal) {
47645 var t1 = e.leftFace.getTriple(e);
47646 var t2 = e.rightFace.getTriple(e);
47647 var edge = new Edge(t1.u, t2.u);
47648 for (var j = 0; j < hd.edges.length; j++) {
47649 if (hd.edges[j].equals(edge) && hd.edges[j].legal) {
47650 hd.edges[j].legal = false;
47651 break;
47652 }
47653 }
47654 t1.e_p.setFace(e.leftFace);
47655 t1.e_s.setFace(e.leftFace);
47656 t2.e_p.setFace(e.rightFace);
47657 t2.e_s.setFace(e.rightFace);
47658
47659 e.legal = true;
47660 }
47661 holeEdges[b] = e;
47662 } else {
47663 nonHoleEdges.push(e);
47664 }
47665 }
47666
47667 for (var i = 0; i < holeEdges.length; i++) {
47668 var e = holeEdges[i];
47669 if (hole[i].leftFace == null) {
47670 hole[i].leftFace = e.leftFace;
47671 hole[i].leftFace.replace(e, hole[i]);
47672 if (arrayIndex(newFacets, hole[i].leftFace) == -1) {
47673 newFacets.push(hole[i].leftFace);
47674 }
47675 }
47676 if (hole[i].rightFace == null) {
47677 hole[i].rightFace = e.rightFace;
47678 hole[i].rightFace.replace(e, hole[i]);
47679 if (arrayIndex(newFacets, hole[i].rightFace) == -1) {
47680 newFacets.push(hole[i].rightFace);
47681 }
47682 }
47683 }
47684
47685 for (var i = 0; i < nonHoleEdges.length; i++) {
47686 var e = nonHoleEdges[i];
47687 if (!e.legal) {
47688 continue;
47689 }
47690 if (this.JordanTest(hullVertices, e)) {
47691 this.edges.push(e);
47692 if (arrayIndex(newFacets, e.rightFace) == -1) {
47693 newFacets.push(e.rightFace);
47694 }
47695 if (arrayIndex(newFacets, e.leftFace) == -1) {
47696 newFacets.push(e.leftFace);
47697 }
47698 }
47699 }
47700
47701 for (var i in oldFacets ) {
47702 oldFacets[i].descendants = newFacets;
47703 }
47704
47705 for (var i = 0; i < newFacets.length; i++) {
47706 var simplex = newFacets[i].interior(v);
47707 if (simplex == null) {
47708 continue;
47709 } else {
47710 this.addVertex(v, simplex);
47711 break;
47712 }
47713 }
47714
47715 return v;
47716
47717 }
47718
47719 Clustering.prototype.JordanTest = function(pol, e) {
47720 var p = new Vertex((e.v0.x + e.v1.x) * 0.5, (e.v0.y + e.v1.y) * 0.5);
47721 var inside = false;
47722 var i, j = pol.length - 1;
47723 for ( i = 0; i < pol.length; j = i++) {
47724 var p1 = pol[i];
47725 var p2 = pol[j];
47726 if ((((p1.y <= p.y) && (p.y < p2.y)) || ((p2.y <= p.y) && (p.y < p1.y))) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x))
47727 inside = !inside;
47728 }
47729 return inside;
47730 }
47731
47732 Clustering.prototype.mergeForResolution = function(resolution, circleGap, circleOverlap) {
47733 this.deleteEdges = new BinaryHeap(function(e) {
47734 return e.weight;
47735 });
47736 this.weightEdges(resolution, circleGap, circleOverlap);
47737 var index = 0;
47738 while (this.deleteEdges.size() > 0) {
47739 var e = this.deleteEdges.pop();
47740 if (e.legal) {
47741 var l = this.edges.length;
47742 var newVertex = this.mergeVertices(e);
47743 newVertex.CalculateRadius(resolution);
47744 for (var k = l; k < this.edges.length; k++) {
47745 var eNew = this.edges[k];
47746 if (eNew.legal) {
47747 if( circleGap != 0 ){
47748 eNew.weight = eNew.length / (eNew.v0.radius + eNew.v1.radius + circleGap * resolution );
47749 }
47750 else if( circleOverlap.overlap == 0 ){
47751 eNew.weight = eNew.length / (eNew.v0.radius + eNew.v1.radius);
47752 }
47753 else {
47754 var r1 = eNew.v0.radius;
47755 var r2 = eNew.v1.radius;
47756 var r = eNew.length;
47757 if( r < r1 + r2 ){
47758 if( circleOverlap.type == 'diameter' ){
47759 var ol1 = (r2-(r-r1)) / r1 / 2;
47760 var ol2 = (r1-(r-r2)) / r2 / 2;
47761 var ol = Math.max(ol1,ol2);
47762 eNew.weight = circleOverlap.overlap / ol;
47763 }
47764 if( circleOverlap.type == 'area' ){
47765 if( !(r+r1 < r2 || r+r2 < r1) ){
47766 var A = r2*r2*Math.acos((r*r+r2*r2-r1*r1)/(2*r*r2))+r1*r1*Math.acos((r*r+r1*r1-r2*r2)/(2*r*r1))-1/2*Math.sqrt((-r+r1+r2)*(r-r1+r2)*(r+r1-r2)*(r+r1+r2));
47767 var ol1 = A / (Math.PI*r1*r1);
47768 var ol2 = A / (Math.PI*r2*r2);
47769 var ol = Math.max(ol1,ol2);
47770 eNew.weight = circleOverlap.overlap / ol;
47771 }
47772 else {
47773 eNew.weight = 0;
47774 }
47775 }
47776 }
47777 }
47778 if (eNew.weight < 1) {
47779 this.deleteEdges.push(eNew);
47780 }
47781 }
47782 }
47783 }
47784 }
47785 }
47786
47787 Clustering.prototype.weightEdges = function(resolution, circleGap, circleOverlap) {
47788 for (var i = 0; i < this.vertices.length; i++) {
47789 if (this.vertices[i].legal) {
47790 this.vertices[i].CalculateRadius(resolution);
47791 }
47792 }
47793 var newEdges = [];
47794 for (var i = 0; i < this.edges.length; i++) {
47795 var e = this.edges[i];
47796 if (e.legal) {
47797 if (!e.v0.legal || !e.v1.legal) {
47798 e.weight = 1;
47799 } else {
47800 if( circleGap != 0 ){
47801 e.weight = e.length / (e.v0.radius + e.v1.radius + circleGap * resolution );
47802 }
47803 else if( circleOverlap.overlap == 0 ){
47804 e.weight = e.length / (e.v0.radius + e.v1.radius);
47805 }
47806 else {
47807 var r1 = e.v0.radius;
47808 var r2 = e.v1.radius;
47809 var r = e.length;
47810 if( r < r1 + r2 ){
47811 if( circleOverlap.type == 'diameter' ){
47812 var ol1 = (r2-(r-r1)) / r1 / 2;
47813 var ol2 = (r1-(r-r2)) / r2 / 2;
47814 var ol = Math.max(ol1,ol2);
47815 e.weight = circleOverlap.overlap / ol;
47816 }
47817 if( circleOverlap.type == 'area' ){
47818 if( !(r+r1 < r2 || r+r2 < r1) ){
47819 var A = r2*r2*Math.acos((r*r+r2*r2-r1*r1)/(2*r*r2))+r1*r1*Math.acos((r*r+r1*r1-r2*r2)/(2*r*r1))-1/2*Math.sqrt((-r+r1+r2)*(r-r1+r2)*(r+r1-r2)*(r+r1+r2));
47820 var ol1 = A / (Math.PI*r1*r1);
47821 var ol2 = A / (Math.PI*r2*r2);
47822 var ol = Math.max(ol1,ol2);
47823 e.weight = circleOverlap.overlap / ol;
47824 }
47825 else {
47826 e.weight = 0;
47827 }
47828 }
47829 }
47830 }
47831 if (e.weight < 1) {
47832 this.deleteEdges.push(e);
47833 }
47834 }
47835 newEdges.push(e);
47836 }
47837 }
47838 this.edges = newEdges;
47839 }
47840
47841 Clustering.prototype.ValidityTest = function() {
47842 console.info("Test 1: Valid Delaunay ...");
47843 /*
47844 var leafs = [];
47845 var triangles = this.boundingTriangle.descendants;
47846 var j = 0;
47847 while( triangles.length > j ){
47848 var t = triangles[j];
47849 if( t.taken == undefined ){
47850 t.taken = true;
47851 if( this.isLeaf(t) ){
47852 leafs.push(t);
47853 }
47854 else {
47855 triangles = triangles.concat(t.descendants);
47856 }
47857 }
47858 j++;
47859 }
47860 console.info(" Number of Triangles: "+leafs.length);
47861
47862 var c = 0;
47863 for( i in this.edges ){
47864 if( this.edges[i].legal ){
47865 c++;
47866 }
47867 }
47868 console.info(" Number of Edges: "+c);*/
47869 /*
47870
47871 for( var i=0; i<leafs.length; i++ ){
47872 for( var j=0; j<vertices.length; j++ ){
47873 if( !leafs[i].contains(vertices[j]) && leafs[i].inCircumcircle(vertices[j]) ){
47874 console.info(leafs[i],vertices[j]);
47875
47876 }
47877 }
47878 }
47879 */
47880
47881 //console.info("Test 2: Edges Facets (null) ...");
47882 for (i in this.edges ) {
47883 var e = this.edges[i];
47884 if (e.leftFace == null || e.rightFace == null) {
47885 console.info(e);
47886 alert();
47887 }
47888 }
47889
47890 //console.info("Test 3: Edges Facets ...");
47891 var leftOf = function(v1, v2, v) {
47892 var x2 = v1.x - v2.x;
47893 var x3 = v1.x - v.x;
47894 var y2 = v1.y - v2.y;
47895 var y3 = v1.y - v.y;
47896 if (x2 * y3 - y2 * x3 < 0) {
47897 return true;
47898 }
47899 return false;
47900 }
47901 var c = 0;
47902 for (i in this.edges ) {
47903 var e = this.edges[i];
47904 var t1 = e.leftFace.getTriple(e);
47905 var t2 = e.rightFace.getTriple(e);
47906 if (e.v0.y == e.v1.y) {
47907 if (t1.u.y > t2.u.y) {
47908 console.info("equal y conflict ...");
47909 console.info(e);
47910 alert();
47911 c++;
47912 }
47913 } else {
47914 var v1, v2;
47915 if (e.v0.y > e.v1.y) {
47916 v1 = e.v0;
47917 v2 = e.v1;
47918 } else {
47919 v1 = e.v1;
47920 v2 = e.v0;
47921 }
47922 if (!leftOf(v1, v2, t1.u)) {
47923 console.info("left right conflict ... left is right");
47924 console.info(e);
47925 alert();
47926 c++;
47927 }
47928 if (leftOf(v1, v2, t2.u)) {
47929 console.info("left right conflict ... right is left");
47930 console.info(e);
47931 alert();
47932 c++;
47933 }
47934 }
47935 }
47936 //console.info("Number of Edges: "+this.edges.length);
47937 //console.info("Number of Conflicts: "+c);
47938
47939 for (i in this.edges ) {
47940 if (this.edges[i].legal) {
47941 var e = this.edges[i];
47942 var tr0 = e.leftFace.getTriple(e);
47943 var tr1 = e.rightFace.getTriple(e);
47944 if (!tr0.e_p.legal || !tr0.e_s.legal || !tr1.e_p.legal || !tr1.e_s.legal) {
47945 console.info(e);
47946 console.info("conflict in edge continuity");
47947 return;
47948 }
47949 }
47950 }
47951
47952 }
47953 function BinaryHeap(scoreFunction) {
47954 this.content = [];
47955 this.scoreFunction = scoreFunction;
47956 }
47957
47958 BinaryHeap.prototype = {
47959 push : function(element) {
47960 // Add the new element to the end of the array.
47961 this.content.push(element);
47962 // Allow it to bubble up.
47963 this.bubbleUp(this.content.length - 1);
47964 },
47965
47966 pop : function() {
47967 // Store the first element so we can return it later.
47968 var result = this.content[0];
47969 // Get the element at the end of the array.
47970 var end = this.content.pop();
47971 // If there are any elements left, put the end element at the
47972 // start, and let it sink down.
47973 if (this.content.length > 0) {
47974 this.content[0] = end;
47975 this.sinkDown(0);
47976 }
47977 return result;
47978 },
47979
47980 remove : function(node) {
47981 var len = this.content.length;
47982 // To remove a value, we must search through the array to find
47983 // it.
47984 for (var i = 0; i < len; i++) {
47985 if (this.content[i] == node) {
47986 // When it is found, the process seen in 'pop' is repeated
47987 // to fill up the hole.
47988 var end = this.content.pop();
47989 if (i != len - 1) {
47990 this.content[i] = end;
47991 if (this.scoreFunction(end) < this.scoreFunction(node))
47992 this.bubbleUp(i);
47993 else
47994 this.sinkDown(i);
47995 }
47996 return;
47997 }
47998 }
47999 throw new Error("Node not found.");
48000 },
48001
48002 size : function() {
48003 return this.content.length;
48004 },
48005
48006 bubbleUp : function(n) {
48007 // Fetch the element that has to be moved.
48008 var element = this.content[n];
48009 // When at 0, an element can not go up any further.
48010 while (n > 0) {
48011 // Compute the parent element's index, and fetch it.
48012 var parentN = Math.floor((n + 1) / 2) - 1, parent = this.content[parentN];
48013 // Swap the elements if the parent is greater.
48014 if (this.scoreFunction(element) < this.scoreFunction(parent)) {
48015 this.content[parentN] = element;
48016 this.content[n] = parent;
48017 // Update 'n' to continue at the new position.
48018 n = parentN;
48019
48020 }
48021 // Found a parent that is less, no need to move it further.
48022 else {
48023 break;
48024 }
48025 }
48026 },
48027
48028 sinkDown : function(n) {
48029 // Look up the target element and its score.
48030 var length = this.content.length, element = this.content[n], elemScore = this.scoreFunction(element);
48031
48032 while (true) {
48033 // Compute the indices of the child elements.
48034 var child2N = (n + 1) * 2, child1N = child2N - 1;
48035 // This is used to store the new position of the element,
48036 // if any.
48037 var swap = null;
48038 // If the first child exists (is inside the array)...
48039 if (child1N < length) {
48040 // Look it up and compute its score.
48041 var child1 = this.content[child1N], child1Score = this.scoreFunction(child1);
48042 // If the score is less than our element's, we need to swap.
48043 if (child1Score < elemScore)
48044 swap = child1N;
48045 }
48046 // Do the same checks for the other child.
48047 if (child2N < length) {
48048 var child2 = this.content[child2N], child2Score = this.scoreFunction(child2);
48049 if (child2Score < (swap == null ? elemScore : child1Score))
48050 swap = child2N;
48051 }
48052
48053 // If the element needs to be moved, swap it, and continue.
48054 if (swap != null) {
48055 this.content[n] = this.content[swap];
48056 this.content[swap] = element;
48057 n = swap;
48058 }
48059 // Otherwise, we are done.
48060 else {
48061 break;
48062 }
48063 }
48064 }
48065 };
48066 /*
48067 * Dropdown.js
48068 *
48069 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48070 *
48071 * This library is free software; you can redistribute it and/or
48072 * modify it under the terms of the GNU Lesser General Public
48073 * License as published by the Free Software Foundation; either
48074 * version 3 of the License, or (at your option) any later version.
48075 *
48076 * This library is distributed in the hope that it will be useful,
48077 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48078 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48079 * Lesser General Public License for more details.
48080 *
48081 * You should have received a copy of the GNU Lesser General Public
48082 * License along with this library; if not, write to the Free Software
48083 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48084 * MA 02110-1301 USA
48085 */
48086
48087 /**
48088 * @class Dropdown
48089 * Implementation for Dropdown box
48090 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48091 * @release 1.0
48092 * @release date: 2012-07-27
48093 * @version date: 2012-07-27
48094 *
48095 * @param {HTML object} parent parent div for the dropdown box
48096 * @param {Array} elements list of dropdown entries
48097 * @param {String} title dropdown button title
48098 */
48099 function Dropdown(parent, elements, title, maxListHeight) {
48100
48101 var dropdown = this;
48102 this.visibility = false;
48103 this.div = document.createElement("div");
48104 this.div.setAttribute('class', 'dropdown');
48105
48106 this.selection = document.createElement("div");
48107 this.selection.setAttribute('class', 'dropdownSelection');
48108 parent.appendChild(this.div);
48109
48110 var leftBorder = document.createElement("div");
48111 leftBorder.setAttribute('class', 'dropdownLeft');
48112 this.div.appendChild(leftBorder);
48113
48114 this.div.appendChild(this.selection);
48115
48116 var dropdownButton = document.createElement("div");
48117 this.div.appendChild(dropdownButton);
48118 if (elements.length > 1) {
48119 dropdownButton.setAttribute('class', 'dropdownButtonEnabled');
48120 } else {
48121 dropdownButton.setAttribute('class', 'dropdownButtonDisabled');
48122 }
48123 dropdownButton.onclick = function() {
48124 if (elements.length > 1) {
48125 dropdown.changeVisibility();
48126 }
48127 }
48128 dropdownButton.title = title;
48129
48130 this.getValue = function() {
48131 return this.selectedEntry.innerHTML;
48132 };
48133
48134 var entryMenu = document.createElement("div");
48135 entryMenu.setAttribute('class', 'dropdownMenu');
48136 this.div.appendChild(entryMenu);
48137 if (typeof maxListHeight !== "undefined")
48138 $(entryMenu).height(maxListHeight);
48139
48140 var entries = document.createElement("dl");
48141 var addEntry = function(e) {
48142 var entry = document.createElement("dt");
48143 entry.setAttribute('class', 'dropdownUnselectedEntry');
48144 entry.innerHTML = e.name;
48145 entry.onclick = function() {
48146 e.onclick();
48147 dropdown.changeVisibility();
48148 dropdown.changeEntries(e);
48149 }
48150 entries.appendChild(entry);
48151 e.entry = entry;
48152 }
48153 for (var i = 0; i < elements.length; i++) {
48154 addEntry(elements[i]);
48155 }
48156 entryMenu.appendChild(entries);
48157 this.selection.style.width = entryMenu.offsetWidth + "px";
48158 entryMenu.style.width = (entryMenu.offsetWidth + leftBorder.offsetWidth + dropdownButton.offsetWidth - 2) + "px";
48159 this.div.style.maxHeight = this.div.offsetHeight + "px";
48160
48161 entryMenu.style.display = 'none';
48162
48163 this.setEntry = function(index) {
48164 if ( typeof (index) == "undefined") {
48165 if ((elements) && elements.length > 0) {
48166 this.changeEntries(elements[0]);
48167 }
48168 } else {
48169 this.changeEntries(elements[index]);
48170 }
48171 }
48172
48173 this.changeEntries = function(element) {
48174 if (this.selectedEntry) {
48175 this.selectedEntry.setAttribute('class', 'dropdownUnselectedEntry');
48176 }
48177 this.selectedEntry = element.entry;
48178 this.selectedEntry.setAttribute('class', 'dropdownSelectedEntry');
48179 this.selection.innerHTML = "<div style='display:inline-block;vertical-align:middle;'>" + element.name + "</div>";
48180 }
48181
48182 this.changeVisibility = function() {
48183 this.visibility = !this.visibility;
48184 if (this.visibility) {
48185 entryMenu.style.display = "block";
48186 } else {
48187 entryMenu.style.display = "none";
48188 }
48189 }
48190 }
48191 /*
48192 * MapZoomSlider.js
48193 *
48194 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48195 *
48196 * This library is free software; you can redistribute it and/or
48197 * modify it under the terms of the GNU Lesser General Public
48198 * License as published by the Free Software Foundation; either
48199 * version 3 of the License, or (at your option) any later version.
48200 *
48201 * This library is distributed in the hope that it will be useful,
48202 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48203 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48204 * Lesser General Public License for more details.
48205 *
48206 * You should have received a copy of the GNU Lesser General Public
48207 * License along with this library; if not, write to the Free Software
48208 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48209 * MA 02110-1301 USA
48210 */
48211
48212 /**
48213 * @class MapZoomSlider
48214 * GeoTemCo style for map zoom control
48215 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48216 * @release 1.0
48217 * @release date: 2012-07-27
48218 * @version date: 2012-07-27
48219 */
48220 function MapZoomSlider(parent, orientation) {
48221
48222 this.parent = parent;
48223
48224 var zs = this;
48225 this.div = document.createElement("div");
48226 this.div.setAttribute('class', 'sliderStyle-' + orientation);
48227
48228 var sliderContainer = document.createElement("div");
48229 sliderContainer.setAttribute('class', 'zoomSliderContainer-' + orientation);
48230 var sliderDiv = document.createElement("div");
48231 sliderDiv.tabIndex = 1;
48232 var sliderInputDiv = document.createElement("div");
48233 sliderDiv.appendChild(sliderInputDiv);
48234 sliderContainer.appendChild(sliderDiv);
48235 this.slider = new Slider(sliderDiv, sliderInputDiv, orientation);
48236 this.div.appendChild(sliderContainer);
48237
48238 var zoomIn = document.createElement("img");
48239 zoomIn.src = GeoTemConfig.path + "zoom_in.png";
48240 zoomIn.setAttribute('class', 'zoomSliderIn-' + orientation);
48241 zoomIn.onclick = function() {
48242 zs.parent.zoom(1);
48243 }
48244 this.div.appendChild(zoomIn);
48245
48246 var zoomOut = document.createElement("img");
48247 zoomOut.src = GeoTemConfig.path + "zoom_out.png";
48248 zoomOut.setAttribute('class', 'zoomSliderOut-' + orientation);
48249 zoomOut.onclick = function() {
48250 zs.parent.zoom(-1);
48251 }
48252 this.div.appendChild(zoomOut);
48253
48254 this.slider.onclick = function() {
48255 console.info(zs.slider.getValue());
48256 }
48257
48258 this.slider.handle.onmousedown = function() {
48259 var oldValue = zs.slider.getValue();
48260 document.onmouseup = function() {
48261 if (!zs.parent.zoom((zs.slider.getValue() - oldValue) / zs.max * zs.levels)) {
48262 zs.setValue(oldValue);
48263 }
48264 document.onmouseup = null;
48265 }
48266 }
48267
48268 this.setValue = function(value) {
48269 this.slider.setValue(value / this.levels * this.max);
48270 }
48271
48272 this.setMaxAndLevels = function(max, levels) {
48273 this.max = max;
48274 this.levels = levels;
48275 this.slider.setMaximum(max);
48276 }
48277 // this.setMaxAndLevels(1000,parent.openlayersMap.getNumZoomLevels());
48278 // this.setValue(parent.getZoom());
48279
48280 this.setLanguage = function() {
48281 zoomIn.title = GeoTemConfig.getString('zoomIn');
48282 zoomOut.title = GeoTemConfig.getString('zoomOut');
48283 this.slider.handle.title = GeoTemConfig.getString('zoomSlider');
48284 }
48285 }
48286 /*
48287 * MapPopup.js
48288 *
48289 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48290 *
48291 * This library is free software; you can redistribute it and/or
48292 * modify it under the terms of the GNU Lesser General Public
48293 * License as published by the Free Software Foundation; either
48294 * version 3 of the License, or (at your option) any later version.
48295 *
48296 * This library is distributed in the hope that it will be useful,
48297 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48298 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48299 * Lesser General Public License for more details.
48300 *
48301 * You should have received a copy of the GNU Lesser General Public
48302 * License along with this library; if not, write to the Free Software
48303 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48304 * MA 02110-1301 USA
48305 */
48306
48307 /**
48308 * @class MapPopup
48309 * map popup implementaion
48310 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48311 * @release 1.0
48312 * @release date: 2012-07-27
48313 * @version date: 2012-07-27
48314 */
48315 function MapPopup(parent) {
48316
48317 this.parentDiv = parent.gui.mapWindow;
48318
48319 this.initialize = function(x, y, onclose) {
48320
48321 var popup = this;
48322 this.x = x;
48323 this.y = y;
48324
48325 this.popupDiv = document.createElement("div");
48326 this.popupDiv.setAttribute('class', 'ddbPopupDiv');
48327 this.parentDiv.appendChild(this.popupDiv);
48328
48329 this.cancel = document.createElement("div");
48330 this.cancel.setAttribute('class', 'ddbPopupCancel');
48331 this.cancel.title = GeoTemConfig.getString('close');
48332 this.cancel.onclick = function() {
48333 if ( typeof onclose != 'undefined') {
48334 onclose();
48335 }
48336 popup.reset();
48337 }
48338
48339 this.input = document.createElement("div");
48340 this.input.style.maxWidth = Math.floor(this.parentDiv.offsetWidth * 0.75) + "px";
48341 this.input.style.maxHeight = Math.floor(this.parentDiv.offsetHeight * 0.75) + "px";
48342 this.input.setAttribute('class', 'ddbPopupInput');
48343
48344 this.popupDiv.appendChild(this.input);
48345 this.popupDiv.appendChild(this.cancel);
48346
48347 var peak = document.createElement("div");
48348 peak.setAttribute('class', 'popupPeak');
48349 this.popupDiv.appendChild(peak);
48350 var topRight = document.createElement("div");
48351 topRight.setAttribute('class', 'popupTopRight');
48352 this.popupDiv.appendChild(topRight);
48353 var bottomRight = document.createElement("div");
48354 bottomRight.setAttribute('class', 'popupBottomRight');
48355 this.popupDiv.appendChild(bottomRight);
48356 this.popupRight = document.createElement("div");
48357 this.popupRight.setAttribute('class', 'popupRight');
48358 this.popupDiv.appendChild(this.popupRight);
48359 this.popupBottom = document.createElement("div");
48360 this.popupBottom.setAttribute('class', 'popupBottom');
48361 this.popupDiv.appendChild(this.popupBottom);
48362
48363 }
48364
48365 this.setContent = function(content) {
48366 $(this.input).empty();
48367 this.visible = true;
48368 $(this.input).append(content);
48369 this.decorate();
48370 }
48371
48372 this.reset = function() {
48373 $(this.popupDiv).remove();
48374 this.visible = false;
48375 }
48376
48377 this.decorate = function() {
48378 this.popupRight.style.height = (this.popupDiv.offsetHeight - 14) + "px";
48379 this.popupBottom.style.width = (this.popupDiv.offsetWidth - 22) + "px";
48380 this.left = this.x + 9;
48381 this.top = this.y - 10 - this.popupDiv.offsetHeight;
48382 this.popupDiv.style.left = this.left + "px";
48383 this.popupDiv.style.top = this.top + "px";
48384 var shiftX = 0, shiftY = 0;
48385 if (this.popupDiv.offsetTop < parent.gui.headerHeight + 10) {
48386 shiftY = -1 * (parent.gui.headerHeight + 10 - this.popupDiv.offsetTop);
48387 }
48388 if (this.popupDiv.offsetLeft + this.popupDiv.offsetWidth > parent.gui.headerWidth - 10) {
48389 shiftX = -1 * (parent.gui.headerWidth - 10 - this.popupDiv.offsetLeft - this.popupDiv.offsetWidth);
48390 }
48391 parent.shift(shiftX, shiftY);
48392 }
48393
48394 this.shift = function(x, y) {
48395 this.left = this.left - this.x + x;
48396 this.top = this.top - this.y + y;
48397 this.x = x;
48398 this.y = y;
48399 if (this.left + this.popupDiv.offsetWidth > this.parentDiv.offsetWidth) {
48400 this.popupDiv.style.left = 'auto';
48401 this.popupDiv.style.right = (this.parentDiv.offsetWidth - this.left - this.popupDiv.offsetWidth) + "px";
48402 } else {
48403 this.popupDiv.style.right = 'auto';
48404 this.popupDiv.style.left = this.left + "px";
48405 }
48406 this.popupDiv.style.top = this.top + "px";
48407 }
48408 }
48409 /*
48410 * PlacenamePopup.js
48411 *
48412 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48413 *
48414 * This library is free software; you can redistribute it and/or
48415 * modify it under the terms of the GNU Lesser General Public
48416 * License as published by the Free Software Foundation; either
48417 * version 3 of the License, or (at your option) any later version.
48418 *
48419 * This library is distributed in the hope that it will be useful,
48420 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48421 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48422 * Lesser General Public License for more details.
48423 *
48424 * You should have received a copy of the GNU Lesser General Public
48425 * License along with this library; if not, write to the Free Software
48426 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48427 * MA 02110-1301 USA
48428 */
48429
48430 /**
48431 * @class PlacenamePopup
48432 * specific map popup for showing and interacting on placename labels
48433 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48434 * @release 1.0
48435 * @release date: 2012-07-27
48436 * @version date: 2012-07-27
48437 */
48438 function PlacenamePopup(parent) {
48439
48440 this.parentDiv = parent.gui.mapWindow;
48441
48442 this.createPopup = function(x, y, labels) {
48443 this.labels = labels;
48444 var pnPopup = this;
48445 var popup = new MapPopup(parent);
48446 var onClose = function() {
48447 parent.deselection();
48448 pnPopup.reset();
48449 }
48450 popup.initialize(x, y, onClose);
48451 $.extend(this, popup);
48452
48453 this.content = document.createElement("div");
48454 this.inner = document.createElement("div");
48455
48456 this.resultsLabel = document.createElement("div");
48457 this.resultsLabel.setAttribute('class', 'popupDDBResults');
48458 this.content.appendChild(this.resultsLabel);
48459 this.backward = document.createElement("div");
48460 this.backward.setAttribute('class', 'prevItem');
48461 this.content.appendChild(this.backward);
48462 this.backward.onclick = function() {
48463 pnPopup.descriptionIndex--;
48464 pnPopup.showDescription();
48465 }
48466
48467 this.number = document.createElement("div");
48468 this.content.appendChild(this.number);
48469 this.number.style.display = 'none';
48470 this.number.style.fontSize = '13px';
48471
48472 this.forward = document.createElement("div");
48473 this.forward.setAttribute('class', 'nextItem');
48474 this.content.appendChild(this.forward);
48475 this.forward.onclick = function() {
48476 pnPopup.descriptionIndex++;
48477 pnPopup.showDescription();
48478 }
48479 if (parent.options.showDescriptions) {
48480 this.descriptions = document.createElement("div");
48481 this.descriptions.setAttribute('class', 'descriptions');
48482 this.descriptions.onclick = function() {
48483 pnPopup.switchToDescriptionMode();
48484 }
48485 }
48486
48487 this.back = document.createElement("div");
48488 this.back.setAttribute('class', 'back');
48489 this.popupDiv.appendChild(this.back);
48490 this.back.onclick = function() {
48491 pnPopup.back.style.display = "none";
48492 pnPopup.backward.style.display = "none";
48493 pnPopup.forward.style.display = "none";
48494 pnPopup.number.style.display = 'none';
48495 pnPopup.showLabels();
48496 }
48497
48498 this.content.appendChild(this.inner);
48499 this.listLabels();
48500 this.showLabels();
48501
48502 };
48503
48504 this.switchToDescriptionMode = function() {
48505 this.descriptionIndex = 0;
48506 this.descriptionContents = this.activeLabel.descriptions;
48507 this.number.style.display = 'inline-block';
48508 this.inner.style.minWidth = "300px";
48509 this.showDescription();
48510 this.count = this.activeLabel.weight;
48511 this.setCount();
48512 this.back.style.display = "inline-block";
48513 }
48514
48515 this.showDescription = function() {
48516 $(this.inner).empty();
48517 this.inner.appendChild(this.descriptionContents[this.descriptionIndex]);
48518 this.setContent(this.content);
48519 if (this.descriptionContents.length == 1) {
48520 this.backward.style.display = "none";
48521 this.forward.style.display = "none";
48522 } else {
48523 if (this.descriptionIndex == 0) {
48524 this.backward.style.display = "none";
48525 } else {
48526 this.backward.style.display = "inline-block";
48527 }
48528 if (this.descriptionIndex == this.descriptionContents.length - 1) {
48529 this.forward.style.display = "none";
48530 } else {
48531 this.forward.style.display = "inline-block";
48532 }
48533 }
48534 if (this.descriptionContents.length > 1) {
48535 this.number.innerHTML = "#" + (this.descriptionIndex + 1);
48536 } else {
48537 this.number.style.display = 'none';
48538 }
48539 this.decorate();
48540 }
48541
48542 this.setCount = function() {
48543 var c = this.count;
48544 if (c > 1) {
48545 this.resultsLabel.innerHTML = c + " " + GeoTemConfig.getString('results');
48546 } else {
48547 this.resultsLabel.innerHTML = c + " " + GeoTemConfig.getString('result');
48548 }
48549 }
48550
48551 this.listLabels = function() {
48552 var pnPopup = this;
48553 this.labelDivs = [];
48554 this.labelCount = 0;
48555 this.labelsWidth = 0;
48556 for (var i = 0; i < this.labels.length; i++) {
48557 var div = document.createElement("div");
48558 var content = document.createElement("div");
48559 this.labels[i].allStyle += "position: relative; white-space: nowrap;";
48560 content.appendChild(this.labels[i].div);
48561 content.setAttribute('class', 'ddbPopupLabel');
48562 div.appendChild(content);
48563 this.labels[i].div.setAttribute('style', this.labels[i].allStyle + "" + this.labels[i].selectedStyle);
48564 this.input.appendChild(div);
48565 if (this.input.offsetWidth > this.labelsWidth) {
48566 this.labelsWidth = this.input.offsetWidth;
48567 }
48568 this.labels[i].div.setAttribute('style', this.labels[i].allStyle + "" + this.labels[i].unselectedStyle);
48569 this.labelDivs.push(div);
48570 var descriptions = [];
48571 for (var j = 0; j < this.labels[i].elements.length; j++) {
48572 var div = document.createElement("div");
48573 div.innerHTML = this.labels[i].elements[j].description;
48574 descriptions.push(div);
48575 }
48576 this.labels[i].descriptions = descriptions;
48577 if (this.labels[i].place != "all" || i == 0) {
48578 this.labelCount += this.labels[i].weight;
48579 }
48580 }
48581 if ( typeof this.descriptions != 'undefined') {
48582 this.labelsWidth += 20;
48583 }
48584 }
48585
48586 this.showLabels = function() {
48587 $(this.inner).empty();
48588 this.count = this.labelCount;
48589 this.setCount();
48590 for (var i = 0; i < this.labelDivs.length; i++) {
48591 this.inner.appendChild(this.labelDivs[i]);
48592 }
48593 this.inner.style.width = this.labelsWidth + "px";
48594 this.inner.style.minWidth = this.labelsWidth + "px";
48595 this.setContent(this.content);
48596 this.decorate();
48597 }
48598
48599 this.showLabelContent = function(label) {
48600 for (var i = 0; i < this.labels.length; i++) {
48601 if (this.labels[i] == label) {
48602 this.activeLabel = this.labels[i];
48603 if ( typeof this.descriptions != 'undefined') {
48604 this.labelDivs[i].appendChild(this.descriptions);
48605 }
48606 this.decorate();
48607 break;
48608 }
48609 }
48610 }
48611
48612 this.setLanguage = function(language) {
48613 this.language = language;
48614 if (this.visible) {
48615 this.updateTexts();
48616 }
48617 }
48618 };
48619 /*
48620 * Dropdown.js
48621 *
48622 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48623 *
48624 * This library is free software; you can redistribute it and/or
48625 * modify it under the terms of the GNU Lesser General Public
48626 * License as published by the Free Software Foundation; either
48627 * version 3 of the License, or (at your option) any later version.
48628 *
48629 * This library is distributed in the hope that it will be useful,
48630 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48631 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48632 * Lesser General Public License for more details.
48633 *
48634 * You should have received a copy of the GNU Lesser General Public
48635 * License along with this library; if not, write to the Free Software
48636 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48637 * MA 02110-1301 USA
48638 */
48639
48640 /**
48641 * @class Publisher
48642 * Publish/Subscribe mechanism
48643 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48644 * @release 1.0
48645 * @release date: 2012-07-27
48646 * @version date: 2012-07-27
48647 */
48648 if ( typeof Publisher == 'undefined') {
48649
48650 Publisher = function() {
48651
48652 var topics = [];
48653
48654 this.Get = function(topic) {
48655 var value = topics[topic];
48656 if (!value || !(value instanceof Array)) {
48657 value = topics[topic] = [];
48658 }
48659 return value;
48660 };
48661
48662 this.Publish = function(topic, data, publisher) {
48663 var subscribers = this.Get(topic);
48664 for (var i = 0; i < subscribers.length; i++) {
48665 if (publisher == null || subscribers[i].client != publisher) {
48666 subscribers[i].callback(data);
48667 }
48668 }
48669 };
48670
48671 this.Subscribe = function(topic, subscriber, callback) {
48672 var subscribers = this.Get(topic);
48673 subscribers.push({
48674 client : subscriber,
48675 callback : callback
48676 });
48677 };
48678
48679 this.Unsubscribe = function(topic, unsubscriber) {
48680 var subscribers = this.Get(topic);
48681 for (var i = 0; i < subscribers.length; i++) {
48682 if (subscribers[i].client == unsubscriber) {
48683 subscribers.splice(i, 1);
48684 return;
48685 }
48686 }
48687 };
48688
48689 return this;
48690
48691 }();
48692
48693 }
48694 /*
48695 * WidgetWrapper.js
48696 *
48697 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48698 *
48699 * This library is free software; you can redistribute it and/or
48700 * modify it under the terms of the GNU Lesser General Public
48701 * License as published by the Free Software Foundation; either
48702 * version 3 of the License, or (at your option) any later version.
48703 *
48704 * This library is distributed in the hope that it will be useful,
48705 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48706 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48707 * Lesser General Public License for more details.
48708 *
48709 * You should have received a copy of the GNU Lesser General Public
48710 * License along with this library; if not, write to the Free Software
48711 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48712 * MA 02110-1301 USA
48713 */
48714
48715 /**
48716 * @class WidgetWrapper
48717 * Interface-like implementation for widgets interaction to each other; aimed to be modified for dynamic data sources
48718 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48719 * @release 1.0
48720 * @release date: 2012-07-27
48721 * @version date: 2012-07-27
48722 *
48723 * @param {Object} widget either a map, time or table widget
48724 */
48725 WidgetWrapper = function() {
48726
48727 var wrapper = this;
48728
48729 this.setWidget = function(widget) {
48730 this.widget = widget;
48731 }
48732
48733 this.display = function(data) {
48734 if ( data instanceof Array) {
48735 GeoTemConfig.datasets = data;
48736 if ( typeof wrapper.widget != 'undefined') {
48737 this.widget.initWidget(data);
48738 }
48739 }
48740 };
48741
48742 Publisher.Subscribe('highlight', this, function(data) {
48743 if (data == undefined) {
48744 return;
48745 }
48746 if ( typeof wrapper.widget != 'undefined') {
48747 wrapper.widget.highlightChanged(data);
48748 }
48749 });
48750
48751 Publisher.Subscribe('selection', this, function(data) {
48752 if ( typeof wrapper.widget != 'undefined') {
48753 wrapper.widget.selectionChanged(data);
48754 }
48755 });
48756
48757 Publisher.Subscribe('filterData', this, function(data) {
48758 wrapper.display(data);
48759 });
48760
48761 Publisher.Subscribe('rise', this, function(id) {
48762 if ( typeof wrapper.widget != 'undefined' && typeof wrapper.widget.riseLayer != 'undefined') {
48763 wrapper.widget.riseLayer(id);
48764 }
48765 });
48766
48767 Publisher.Subscribe('resizeWidget', this, function() {
48768 if ( typeof wrapper.widget != 'undefined' && typeof wrapper.widget.gui != 'undefined' && typeof wrapper.widget.gui.resize != 'undefined' ) {
48769 wrapper.widget.gui.resize();
48770 }
48771 });
48772
48773 this.triggerRefining = function(datasets) {
48774 Publisher.Publish('filterData', datasets, null);
48775 };
48776
48777 this.triggerSelection = function(selectedObjects) {
48778 Publisher.Publish('selection', selectedObjects, this);
48779 };
48780
48781 this.triggerHighlight = function(highlightedObjects) {
48782 Publisher.Publish('highlight', highlightedObjects, this);
48783 };
48784
48785 this.triggerRise = function(id) {
48786 Publisher.Publish('rise', id);
48787 };
48788
48789 };
48790 /*
48791 * final.js
48792 *
48793 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
48794 *
48795 * This library is free software; you can redistribute it and/or
48796 * modify it under the terms of the GNU Lesser General Public
48797 * License as published by the Free Software Foundation; either
48798 * version 3 of the License, or (at your option) any later version.
48799 *
48800 * This library is distributed in the hope that it will be useful,
48801 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48802 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48803 * Lesser General Public License for more details.
48804 *
48805 * You should have received a copy of the GNU Lesser General Public
48806 * License along with this library; if not, write to the Free Software
48807 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
48808 * MA 02110-1301 USA
48809 */
48810
48811 /**
48812 * code which is included after all other sources have been included for the minified version
48813 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
48814 * @release 1.0
48815 * @release date: 2012-07-27
48816 * @version date: 2012-07-27
48817 */
48818
48819 OpenLayers.Util.getImagesLocation = function() {
48820 return GeoTemCoMinifier_urlPrefix + "lib/openlayers/img/";
48821 };
48822
48823 OpenLayers._getScriptLocation = function() {
48824 return GeoTemCoMinifier_urlPrefix + "lib/openlayers/";
48825 };
48826
48827 GeoTemConfig.configure(GeoTemCoMinifier_urlPrefix);
48828 })(jQuery);